UIViewAlertForUnsatisfiableConstraints nasıl tuzaklanır?


234

Hata ayıklayıcı günlüğümde bir hata görüyorum:

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.

Bu çağrıyı nasıl yakalayabilirim? Kodumun hiçbir yerinde görünmüyor.

Screenshot1


10 durumun 9'unda: bunun nedeni sadece: yoru storyboard'daki bazı görünüm veya öğeler için "Yüklü" seçeneğinin işaretini kaldırmanız gerekir. (Örneğin, sadece bir geliştirme düğmesi veya daha fazla ihtiyacınız olmayan bir şey.) Genel olarak, "Yüklü Değil" işlevini kötü işler: Genellikle Yüklenmemiş öğe olmadan anlamsız hale gelen kısıtlamalar bırakır. Genellikle çözüm, "Yüklü Değil" etrafında oturan, unuttuğunuz öğeleri silmektir - sadece onları silin.
Fattie

Yanıtlar:


442

Bu mesaj bana yardımcı ÇOK !

Önerilen eylemle UIViewAlertForUnsatisfiableConstraints sembolik kesme noktasını ekledim :

Obj-C projesi

po [[UIWindow keyWindow] _autolayoutTrace]

Objective-C projesinde özel eylem ile sembolik kesme noktası

Hızlı proje

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

Özel eylem ile sembolik kesme noktası

Bu ipucu ile kütük daha ayrıntılı hale geldi ve hangi görüşün kısıtlamanın kırıldığını tanımlamak daha kolay oldu.

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

Sonra yürütmeyi duraklattım Duraklat ve sorunlu görünümün arka plan rengini komutla değiştirdim (elbette nesnenizin0x7f88a8cc2050 bellek adresiyle değiştirerek ) ...

Obj-Cı

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

Swift 3.0

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

... ve sonuç Harikaydı!

Hinted View

Tek kelimeyle muhteşem! Umarım yardımcı olur.


3
@ iAnurag Yürütme duraklatıldığında, konsol alanında komutları çalıştırabilirsiniz.
Thomás Calmon

2
@TomCalmon Aynı şeyi yaptım ... ama aşağıdaki hatayı gösteriyor 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]nilbenim için döner
Igor Andreev

2
0x7f88a8cc2050'yi nesnenizin bellek adresiyle değiştirdiğinizden ve yürütme duraklatıldığında komutu konsolda çalıştırdığınızdan emin olun.
Tom Howard

3
Unfreakingbelievable. Burada büyük ipucu, tamamen doğrudan konuya gitmeme yardımcı oldu. Öğe kırmızıya döndüğünde, mümkünse yürütmeye devam edin, vurgulamayı göreceksiniz.
Aaron

255

Bir eklemek isteyeceksiniz Symbolic Breakpoint. Apple, bunun nasıl yapılacağı konusunda mükemmel bir rehber sunuyor .

  1. Kesme Noktası Gezgini'ni açın cmd+7( cmd+8Xcode 9'da)
  2. AddSol alttaki düğmeyi tıklayın
  3. seçmek Add Symbolic Breakpoint...
  4. Yazan yere Symbolsadece yazınUIViewAlertForUnsatisfiableConstraints

Ayrıca diğer kesme noktaları gibi davranabilir, açabilir ve kapatabilir, eylemler ekleyebilir veya mesajlar kaydedebilirsiniz.


55
Sorunu bu ipucu ile nasıl daha iyi hata ayıklayabileceğimi anlamıyorum. Sembolik bir kırılma noktası ekledim, ancak yine de sorun ne kadar bilgi vermiyor. Tek yol satır satır okumaya ve soruna neyin neden olduğunu anlamaya çalışmaktır ... aksi takdirde kısıtlamaları temizlemek ve bunları tekrar önizleme görünümü ile birlikte eklemek en çok yardımcı olacaktır!
Alex Cio

11
Bu, kırılma noktasında durduktan sonra daha fazla bilgi edinmenize
fabb

1
Sadece kısıtlayıcılara doğrudan IB'de tanımlayıcılar verebileceğinizi ekleyerek, hata ayıklama yaparken göreceğiniz ad budur.
Mark A. Donohoe

2
(@MarqueIV'deki takip) NSLayoutConstraint, identifieriOS 7 - Xcode 7 ve üstü sürümlerden beri hem IB Storyboard'lardan hem de koddan ayarlanabilen bir özelliğe sahiptir . Tanımlayıcıyı ayarlayarak, hata ayıklama günlüğünde sistem tarafından oluşturulan ve kullanıcı tarafından oluşturulan kısıtlamalar arasında daha kolay ayrım yapabilirsiniz, örneğin myConstraint.identifier = "centered image"(kaynak ve örnekler: useyourloaf.com/blog/using-identifiers-to-debug-autolayout )
PDK

@AlexCio Nasıl yardımcı olur? En az yaptığı şey, gerçekleştiği anda duraklar. Geri izleyebileceğiniz ve kökeni bulabileceğiniz bir yığın izlemesi verir ...
Bal

10

Stephen'ın tavsiyelerini takip etti ve kodu ve whoa hatalarını ayıklamaya çalıştı! işe yaradı. Yanıt, hata ayıklama iletisinin kendisinde yatar.

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

Yukarıdaki satır, çalışma zamanının bu kısıtlamayı kaldırarak çalıştığını gösterir. Düğmenizde Yatay Boşluk bırakmaya ihtiyacınız olmayabilir (MPKnockoutButton). Bu kısıtlamayı temizledikten sonra, çalışma zamanında şikayet etmez ve istediğiniz davranışı elde edersiniz.


3
Derleyici? Çalışma zamanını mı kastediyorsun? Derleyici kısıtlamayı kaldırmadı. Derleyici çalışma zamanı ile başa çıkmak için orada bıraktı, bu nedenle çalışma zamanı sırasında "kısıtlamayı kırarak kurtar" .
drhr

Evet çalışma süresi demek
istedim

2

Sistemin kırmak zorunda olduğu kısıtlamaları kaldırmaya çalıştığımda, kısıtlarım artık IB'yi tatmin edecek kadar yeterli değil (yani IB'deki "eksik kısıtlamalar" gösterileri, yani eksik ve kullanılmayacaklar). Aslında, düşük önceliğe kırmak istediği kısıtlamayı ayarlayarak bunun üstesinden geldim, ki bu (ve bu bir varsayım) sistemin kısıtlamayı incelikle kırmasına izin veriyor. Muhtemelen en iyi çözüm değil, ama sorunumu çözdü ve ortaya çıkan kısıtlamalar mükemmel çalıştı.


2
Genellikle bu, çalışma zamanında kaldırılan bir yer tutucu kısıtlaması kullanmak istediğiniz bir durumdur. Bir kısıtlamayı yer tutucu kısıtlaması yapmak için, kısıt denetçisine gidin ve "Oluşturma zamanında kaldır" ı tıklayın. IB çizim alanındaki kısıtlama I-demeti sembolünün bunu göstermek için maviden griye nasıl döndüğüne dikkat edin.
spencery2

1
Aynı sorunu yaşadım. Kırık kısıtı kaldırdığımda tasarımım bozuldu. Bu yüzden önceliği orta olarak ayarladım.
Jeremy Piednoel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.