วิธีการดักจับบน UIViewAlertForUns ไม่พอใจข้อ จำกัด ?


234

ฉันเห็นข้อผิดพลาดปรากฏในบันทึกการดีบักเกอร์:

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x191f0920 H:[MPKnockoutButton:0x17a876b0]-(34)-[MPDetailSlider:0x17a8bc50](LTR)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

ฉันจะดักการโทรนั้นได้อย่างไร มันไม่ปรากฏที่ใดในรหัสของฉัน

screenshot1


ใน 9 ใน 10 กรณี: เกิดจาก: สำหรับบางมุมมองหรือรายการบนกระดานเรื่องราวของคุณคุณจะยกเลิกการเลือก "ติดตั้ง" (ตัวอย่างเช่นเพียงแค่ปุ่มพัฒนาหรือบางสิ่งที่คุณไม่ต้องการอีกแล้ว) โดยทั่วไปมันจัดการ "ไม่ได้ติดตั้ง" ไม่ดี: มักจะมีข้อ จำกัด ที่ไม่มีความหมายหากไม่มีรายการที่ไม่ได้ติดตั้ง บ่อยครั้งที่การแก้ปัญหาคือเพียงการลบรายการที่คุณลืมเกี่ยวกับการนั่ง "ไม่ได้ติดตั้ง" - เพียงแค่ลบ 'em
Fattie

คำตอบ:


442

โพสต์นี้ช่วยฉันได้มาก !

ฉันเพิ่มUIViewAlertForUnsatisfiableConstraintsสัญลักษณ์เบรกพอยต์พร้อมการดำเนินการที่แนะนำ:

โครงการ Obj-C

po [[UIWindow keyWindow] _autolayoutTrace]

สัญลักษณ์เบรกพอยต์ที่มีการกระทำที่กำหนดเองในโครงการ Objective-C

โครงการสวิฟท์

expr -l objc++ -O -- [[UIWindow keyWindow] _autolayoutTrace]

สัญลักษณ์เบรกพอยต์พร้อมการกระทำที่กำหนดเอง

ด้วยคำใบ้นี้บันทึกมีรายละเอียดมากขึ้นและมันง่ายขึ้นสำหรับฉันที่จะระบุว่ามุมมองใดที่มีข้อ จำกัด แตก

UIWindow:0x7f88a8e4a4a0
|   UILayoutContainerView:0x7f88a8f23b70
|   |   UINavigationTransitionView:0x7f88a8ca1970
|   |   |   UIViewControllerWrapperView:0x7f88a8f2aab0
|   |   |   |   UIView:0x7f88a8ca2880
|   |   |   |   |   *UIView:0x7f88a8ca2a10
|   |   |   |   |   |   *UIButton:0x7f88a8c98820'Archived'
|   |   |   |   |   |   |   UIButtonLabel:0x7f88a8cb0e30'Archived'
|   |   |   |   |   |   *UIButton:0x7f88a8ca22d0'Download'
|   |   |   |   |   |   |   UIButtonLabel:0x7f88a8cb04e0'Download'
|   |   |   |   |   |   *UIButton:0x7f88a8ca1580'Deleted'
|   |   |   |   |   |   |   UIButtonLabel:0x7f88a8caf100'Deleted'
|   |   |   |   |   *UIView:0x7f88a8ca33e0
|   |   |   |   |   *_UILayoutGuide:0x7f88a8ca35b0
|   |   |   |   |   *_UILayoutGuide:0x7f88a8ca4090
|   |   |   |   |   _UIPageViewControllerContentView:0x7f88a8f1a390
|   |   |   |   |   |   _UIQueuingScrollView:0x7f88aa031c00
|   |   |   |   |   |   |   UIView:0x7f88a8f38070
|   |   |   |   |   |   |   UIView:0x7f88a8f381e0
|   |   |   |   |   |   |   |   UIView:0x7f88a8f39fa0, MISSING HOST CONSTRAINTS
|   |   |   |   |   |   |   |   |   *UIButton:0x7f88a8cb9bf0'Retrieve data'- AMBIGUOUS LAYOUT for UIButton:0x7f88a8cb9bf0'Retrieve data'.minX{id: 170}, UIButton:0x7f88a8cb9bf0'Retrieve data'.minY{id: 171}
|   |   |   |   |   |   |   |   |   *UIImageView:0x7f88a8f3ad80- AMBIGUOUS LAYOUT for UIImageView:0x7f88a8f3ad80.minX{id: 172}, UIImageView:0x7f88a8f3ad80.minY{id: 173}
|   |   |   |   |   |   |   |   |   *App.RecordInfoView:0x7f88a8cbe530- AMBIGUOUS LAYOUT for App.RecordInfoView:0x7f88a8cbe530.minX{id: 174}, App.RecordInfoView:0x7f88a8cbe530.minY{id: 175}, App.RecordInfoView:0x7f88a8cbe530.Width{id: 176}, App.RecordInfoView:0x7f88a8cbe530.Height{id: 177}
|   |   |   |   |   |   |   |   |   |   +UIView:0x7f88a8cc1d30- AMBIGUOUS LAYOUT for UIView:0x7f88a8cc1d30.minX{id: 178}, UIView:0x7f88a8cc1d30.minY{id: 179}, UIView:0x7f88a8cc1d30.Width{id: 180}, UIView:0x7f88a8cc1d30.Height{id: 181}
|   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8cc1ec0- AMBIGUOUS LAYOUT for UIView:0x7f88a8cc1ec0.minX{id: 153}, UIView:0x7f88a8cc1ec0.minY{id: 151}, UIView:0x7f88a8cc1ec0.Width{id: 154}, UIView:0x7f88a8cc1ec0.Height{id: 165}
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8e68e10- AMBIGUOUS LAYOUT for UIView:0x7f88a8e68e10.minX{id: 155}, UIView:0x7f88a8e68e10.minY{id: 150}, UIView:0x7f88a8e68e10.Width{id: 156}
|   |   |   |   |   |   |   |   |   |   |   |   *UIImageView:0x7f88a8e65de0- AMBIGUOUS LAYOUT for UIImageView:0x7f88a8e65de0.minX{id: 159}, UIImageView:0x7f88a8e65de0.minY{id: 182}
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8e69080'8-6-2015'- AMBIGUOUS LAYOUT for UILabel:0x7f88a8e69080'8-6-2015'.minX{id: 183}, UILabel:0x7f88a8e69080'8-6-2015'.minY{id: 184}, UILabel:0x7f88a8e69080'8-6-2015'.Width{id: 185}
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8cc0690'16:34'- AMBIGUOUS LAYOUT for UILabel:0x7f88a8cc0690'16:34'.minX{id: 186}, UILabel:0x7f88a8cc0690'16:34'.minY{id: 187}, UILabel:0x7f88a8cc0690'16:34'.Width{id: 188}, UILabel:0x7f88a8cc0690'16:34'.Height{id: 189}
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8cc2050- AMBIGUOUS LAYOUT for UIView:0x7f88a8cc2050.minX{id: 161}, UIView:0x7f88a8cc2050.minY{id: 166}, UIView:0x7f88a8cc2050.Width{id: 163}
|   |   |   |   |   |   |   |   |   |   |   |   *UIImageView:0x7f88a8e69d90- AMBIGUOUS LAYOUT for UIImageView:0x7f88a8e69d90.minX{id: 190}, UIImageView:0x7f88a8e69d90.minY{id: 191}, UIImageView:0x7f88a8e69d90.Width{id: 192}, UIImageView:0x7f88a8e69d90.Height{id: 193}
|   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3cc00
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8e618d0
|   |   |   |   |   |   |   |   |   |   |   |   *UIImageView:0x7f88a8e5ba10
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3cd70
|   |   |   |   |   |   |   |   |   |   |   |   *UIImageView:0x7f88a8e58e10
|   |   |   |   |   |   |   |   |   |   |   |   *UIImageView:0x7f88a8e5e7a0
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3cee0
|   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3dc70
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8e64dd0
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8e65290'Average flow rate'
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8e712d0'177.0 ml/s'
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8c97150'1299.4'
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3dde0
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8f3df50'Maximum flow rate'
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8cbfdb0'371.6 ml/s'
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8cc0230'873.5'
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3e2a0
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8f3e410'Total volume'
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8cc0f20'371.6 ml'
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3e870
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8f3ea00'Time do max. flow'
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8cc0ac0'3.6 s'
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3ee10
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8f3efa0'Flow time'
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8cbf980'2.1 s'
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3f3e0
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8f3f570'Voiding time'
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8cc17e0'3.5 s'
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3f9a0
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8f3fb30'Voiding delay'
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8cc1380'1.0 s'
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8e65000
|   |   |   |   |   |   |   |   |   |   |   |   *UIButton:0x7f88a8e52f20'Show'
|   |   |   |   |   |   |   |   |   |   |   |   *UIImageView:0x7f88a8e6e1d0
|   |   |   |   |   |   |   |   |   |   |   |   *UIButton:0x7f88a8e52c90'Send'
|   |   |   |   |   |   |   |   |   |   |   |   *UIImageView:0x7f88a8e61bb0
|   |   |   |   |   |   |   |   |   |   |   |   *UIButton:0x7f88a8e528e0'Delete'
|   |   |   |   |   |   |   |   |   |   |   |   *UIImageView:0x7f88a8e6b3f0
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3ff60
|   |   |   |   |   |   |   |   |   *UIActivityIndicatorView:0x7f88a8cba080
|   |   |   |   |   |   |   |   |   |   UIImageView:0x7f88a8cba700
|   |   |   |   |   |   |   |   |   *_UILayoutGuide:0x7f88a8cc3150
|   |   |   |   |   |   |   |   |   *_UILayoutGuide:0x7f88a8cc3b10
|   |   |   |   |   |   |   UIView:0x7f88a8f339c0
|   |   UINavigationBar:0x7f88a8c96810
|   |   |   _UINavigationBarBackground:0x7f88a8e45c00
|   |   |   |   UIImageView:0x7f88a8e46410
|   |   |   UINavigationItemView:0x7f88a8c97520'App'
|   |   |   |   UILabel:0x7f88a8c97cc0'App'
|   |   |   UINavigationButton:0x7f88a8e3e850
|   |   |   |   UIImageView:0x7f88a8e445b0
|   |   |   _UINavigationBarBackIndicatorView:0x7f88a8f2b530

Legend:
    * - is laid out with auto layout
    + - is laid out manually, but is represented in the layout engine because translatesAutoresizingMaskIntoConstraints = YES
     - layout engine host

จากนั้นฉันหยุดการทำงานชั่วคราว หยุด และเปลี่ยนสีพื้นหลังของมุมมองที่มีปัญหาด้วยคำสั่ง (แทนที่0x7f88a8cc2050ด้วยที่อยู่หน่วยความจำของวัตถุของคุณแน่นอน) ...

Obj-C

expr ((UIView *)0x7f88a8cc2050).backgroundColor = [UIColor redColor]

สวิฟท์ 3.0

expr -l Swift -- import UIKit
expr -l Swift -- unsafeBitCast(0x7f88a8cc2050, to: UIView.self).backgroundColor = UIColor.red

... และผลลัพธ์มันยอดเยี่ยมมาก!

มุมมองคำใบ้

น่าอัศจรรย์เพียง! หวังว่ามันจะช่วย


3
@iAnurag คุณสามารถเรียกใช้คำสั่งในพื้นที่คอนโซลเมื่อการดำเนินการถูกหยุดชั่วคราว
Thomás Calmon

2
@ TomCalmon ฉันทำแบบเดียวกัน ... แต่มันแสดงข้อผิดพลาดดังต่อไปนี้ rror: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0x7f88a8cc2050). The process has been returned to the state before expression evaluation.
iAnurag

2
expr -l objc++ -O -- [[UIWindow keyWindow] _autolayoutTrace]ส่งคืนnilสำหรับฉัน
Igor Andreev

2
ตรวจสอบให้แน่ใจว่าคุณได้แทนที่ 0x7f88a8cc2050 ด้วยที่อยู่หน่วยความจำของวัตถุของคุณและเรียกใช้คำสั่งในคอนโซลเมื่อการดำเนินการหยุดชั่วคราว
Tom Howard

3
Unfreakingbelievable เคล็ดลับที่ดีที่นี่ทั้งหมดช่วยให้ฉันตรงไปที่ปัญหา เมื่อรายการถูกเปลี่ยนเป็นสีแดงให้ดำเนินการต่อหากเป็นไปได้และคุณจะเห็นไฮไลต์
แอรอน

255

Symbolic Breakpointคุณจะต้องการที่จะเพิ่ม Apple ให้คำแนะนำที่ดีเกี่ยวกับวิธีการทำเช่นนี้

  1. เปิดเบรกพอยต์นาวิเกเตอร์cmd+7( cmd+8ใน Xcode 9)
  2. คลิกที่Addปุ่มด้านซ้ายล่าง
  3. เลือก Add Symbolic Breakpoint...
  4. ที่มันบอกว่าSymbolเพียงแค่พิมพ์UIViewAlertForUnsatisfiableConstraints

คุณยังสามารถปฏิบัติต่อมันเหมือนเบรกพอยต์อื่น ๆ เปิดและปิดเพิ่มการกระทำหรือบันทึกข้อความ


55
ฉันไม่เข้าใจว่าฉันจะแก้ไขปัญหาได้ดีขึ้นด้วยคำแนะนำนี้อย่างไร ฉันเพิ่มสัญลักษณ์เบรกพอยต์สัญลักษณ์ แต่ก็ยังไม่ให้ข้อมูลที่เพียงพอแก่ฉันว่าปัญหาคืออะไร วิธีเดียวคือการพยายามอ่านทีละบรรทัดและเข้าใจว่าอะไรเป็นสาเหตุของปัญหา ... มิฉะนั้นการยกเลิกข้อ จำกัด และเพิ่มพวกเขาเข้าด้วยกันอีกครั้งพร้อมกับดูตัวอย่างในมุมมอง asisstent น่าจะช่วยได้มากที่สุด!
Alex Cio

11
สิ่งนี้อาจช่วยให้ได้รับข้อมูลเพิ่มเติมหลังจากหยุดที่เบรกพอยต์: staxmanade.com/2015/06/debugging-ios-autolayout-issues
fabb

1
เพียงเพิ่มว่าตอนนี้คุณสามารถให้ตัวระบุถึงข้อ จำกัด โดยตรงใน IB ดังนั้นเมื่อคุณทำการดีบั๊กนั่นคือชื่อที่คุณจะเห็น
Mark A. Donohoe

2
(ติดตามบน @MarqueIV) NSLayoutConstraintมีidentifierคุณสมบัติตั้งแต่ iOS 7 - Xcode 7 ขึ้นไปซึ่งสามารถตั้งค่าได้ทั้งจากกระดานเรื่องราว IB และจากรหัส ด้วยการตั้งค่าตัวระบุคุณสามารถแยกแยะข้อ จำกัด ระหว่างระบบที่สร้างขึ้นและข้อ จำกัด ที่ผู้ใช้สร้างได้ง่ายขึ้นในบันทึกการดีบักเช่นmyConstraint.identifier = "centered image"(แหล่งที่มา & ตัวอย่าง: useyourloaf.com/blog/using-identifiers-to-debug-autolayout )
PDK

@AlexCio มันช่วยได้อย่างไร? อย่างน้อยก็คือมันหยุดในขณะที่มันเกิดขึ้น มันทำให้กองติดตามที่คุณสามารถ backtrack และหาแหล่งกำเนิด ...
น้ำผึ้ง

10

ทำตามคำแนะนำของสตีเฟ่นและพยายามที่จะแก้ปัญหารหัสและโอ้โห! มันทำงานได้ คำตอบนั้นอยู่ในข้อความดีบั๊กเอง

Will attempt to recover by breaking constraint NSLayoutConstraint:0x191f0920 H:[MPKnockoutButton:0x17a876b0]-(34)-[MPDetailSlider:0x17a8bc50](LTR)>

บรรทัดข้างต้นบอกคุณว่ารันไทม์ทำงานได้โดยลบข้อ จำกัด นี้ อาจเป็นเพราะคุณไม่ต้องการระยะห่างแนวนอนบนปุ่มของคุณ (MPKnockoutButton) เมื่อคุณล้างข้อ จำกัด นี้แล้วมันจะไม่บ่นที่รันไทม์ & คุณจะได้รับพฤติกรรมที่ต้องการ


3
คอมไพเลอร์? คุณหมายถึงรันไทม์หรือไม่ คอมไพเลอร์ไม่ได้ลบข้อ จำกัด คอมไพเลอร์ทิ้งมันไว้ที่นั่นรันไทม์ที่จะจัดการกับเหตุ "กู้โดย จำกัด การทำลาย" ในช่วงรันไทม์
drhr

ใช่ฉันหมายถึงรันไทม์
กลุ่ม

2

เมื่อใดก็ตามที่ฉันพยายามลบข้อ จำกัด ที่ระบบต้องทำลายข้อ จำกัด ของฉันไม่เพียงพอที่จะสนองความต้องการของ IB (เช่น "ข้อ จำกัด ที่หายไป" แสดงใน IB ซึ่งหมายความว่าพวกเขาไม่สมบูรณ์และจะไม่ถูกใช้) จริง ๆ แล้วฉันได้รับสิ่งนี้โดยการตั้งค่าข้อ จำกัด ที่ต้องการแบ่งออกเป็นลำดับความสำคัญต่ำซึ่ง (และนี่คือข้อสมมติ) ทำให้ระบบสามารถแบ่งข้อ จำกัด ได้อย่างสง่างาม อาจไม่ใช่วิธีที่ดีที่สุด แต่แก้ไขปัญหาของฉันและข้อ จำกัด ที่เกิดขึ้นทำงานได้อย่างสมบูรณ์


2
โดยทั่วไปแล้วเป็นสถานการณ์ที่คุณต้องการใช้ข้อ จำกัด ตัวแทนซึ่งถูกลบออกในขณะทำงาน ในการสร้างข้อ จำกัด ตัวยึดตำแหน่งให้ไปที่ตัวตรวจสอบข้อ จำกัด และคลิก "ลบเมื่อเวลาสร้าง" สังเกตว่าสัญลักษณ์ I-beam ที่มีข้อ จำกัด ในพื้นที่วาด IB เปลี่ยนจากสีน้ำเงินเป็นสีเทาเพื่อระบุสิ่งนี้อย่างไร
spencery2 2

1
ฉันมีปัญหาเดียวกัน เมื่อฉันลบข้อ จำกัด ที่ขาดออกการออกแบบของฉันพัง ดังนั้นฉันจึงกำหนดลำดับความสำคัญเป็นสื่อ
Jeremy Piednoel
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.