2012-12-19 19 views
9

Mam pewne problemy z NSLayoutConstraint.Dodawanie i ustawianie NSLayoutConstraint za pomocą kodu

NSLayoutConstraint daje mi wyjątek, jeśli próbuję zmienić constant przy użyciu metody setConstant:. Mam tylko ten problem, gdy dodam ograniczenie wysokości za pomocą kodu.

Po pierwsze, jestem coraz ograniczenie wysokości tak:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"firstAttribute = %d", NSLayoutAttributeWidth]; 
NSArray *filteredArray = [[self constraints] filteredArrayUsingPredicate:predicate]; 
return filteredArray[0]; 

Który daje mi prawo ograniczenia. Mam podklasę NSTextext, gdzie to działa idealnie. Ograniczenia są ustawiane w Konstruktorze interfejsów i mogę ustawić i zmienić stałą.

Teraz mam widok, w którym dodam różne subviews podczas wykonywania. Te subviews znajdują się we własnych NIB, co oznacza, że ​​nie mogę przypiąć ich szerokości i wysokości. Więc pomyślałem, że dodam ograniczenia, gdy tylko widok zostanie dodany do superview. To jest wykonywane w viewDidMoveToSuperview.

// Pin Width & Height 
[self addConstraint:[NSLayoutConstraint constraintWithItem:self 
          attribute:NSLayoutAttributeWidth 
          relatedBy:NSLayoutRelationEqual 
           toItem:nil 
          attribute:NSLayoutAttributeNotAnAttribute 
          multiplier:1.0f 
           constant:self.frame.size.width]]; 
[self addConstraint:[NSLayoutConstraint constraintWithItem:self 
               attribute:NSLayoutAttributeHeight 
               relatedBy:NSLayoutRelationEqual 
                toItem:nil 
               attribute:NSLayoutAttributeNotAnAttribute 
               multiplier:1.0f 
                constant:self.frame.size.height]]; 

Ograniczenia są dodawane, mogę to potwierdzić przy pomocy NSLog.

"<NSLayoutConstraint:0x100605cc0 H:[ITControlPanelChildView:0x100616eb0(269)]>", 
"<NSLayoutConstraint:0x100614410 V:[ITControlPanelChildView:0x100616eb0(317)]>" 

Teraz, wreszcie, gdy próbuję zmienić ograniczenie korzystania [constraint setConstant:somethingDifferent]; otrzymuję następujący wyjątek:

Unable to simultaneously satisfy constraints: 
(
    "<NSLayoutConstraint:0x10192fcb0 V:[ITControlPanelChildView:0x10192e4f0(100)]>", 
    "<NSAutoresizingMaskLayoutConstraint:0x10053ff10 h=--& v=&-- V:[ITControlPanelChildView:0x10192e4f0(317)]>" 
) 

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x10192fcb0 V:[ITControlPanelChildView:0x10192e4f0(100)]> 

To jest właśnie ograniczenie Próbuję zmienić. Czy ktoś może mi wyjaśnić, dlaczego tak się dzieje?


EDIT

Właśnie przeczytałem, że NSAutoresizingMaskLayoutConstraint s dodawane są automatycznie, co można wyłączyć, jeśli ustawisz [self setTranslatesAutoresizingMaskIntoConstraints:NO];.

Jeśli wyłączę to, działa.

Jeszcze lepiej byłoby, gdybym mógł uzyskać dostęp do utworzonych NSAutoresizingMaskLayoutConstraint. Czy ktoś wie, jak to działa?

+0

Myślisz, że dodałeś tę zmianę podczas pisania odpowiedzi! Czy Autolayout jest włączony w Xib w celu wyświetlenia podglądu? Czy możesz pokazać kod, którego używasz, aby dodać wydział? – jrturton

+0

@jrturton Tak, autolayout jest włączony. Może źle mnie zrozumiałeś, działa. Pomyślałem, że byłoby miło, gdybym mógł użyć 'NSAutoresizingMaskLayoutConstraint', które są już dla mnie stworzone, zamiast ich wyłączać i dodawać ograniczenia. Czy rozumiesz, co mam na myśli? – NSAddict

+0

Mam, ale nie możesz. Jestem zaskoczony, że pojawili się w widoku zdefiniowanym na najwyższym poziomie w autolayout xib, dlatego zapytałem o kod. – jrturton

Odpowiedz

8

Jak wskazano w pozostałej części komunikatu dziennika, który nie został dołączony, masz automatyczne ograniczanie, którego nie chcesz lub nie potrzebujesz.

Możesz je usunąć, dodając podgląd. W metodzie używasz powyżej, po prostu dodaj wiersz:

self.translatesAutoresizingMaskIntoConstraints = NO; 

Choć jeśli tworzysz widok w osobnym stalówki, gdzie jest uzyskanie od jego wielkości? Czy nie ma już ograniczeń rozmiaru, do których możesz po prostu tworzyć wyjścia?

1

Mam ten problem dwa razy.

Użyłem techniki opisanej w Programowanie kakao dla Mac OSX 4th Ed przez Hillegass & Preble. Książka zaleca używanie NSBox jako kontenera widokowego i przełączanie widoków za pomocą kodu.Książka zawiera również przydatny kod do ręcznej zmiany rozmiaru zewnętrznego okna zawierającego widok, w którym właśnie się przełączyłeś.

Po raz pierwszy próbowałem swoją technikę mam ten wyjątek:

2013-01-05 22:56:05.103 MyApp[17717:303] Unable to simultaneously satisfy constraints: 
(
    "<NSAutoresizingMaskLayoutConstraint:0x100141330 h=--& v=--& H:[NSView:0x10012fdf0(4)]>", 
"<NSLayoutConstraint:0x1001316c0 H:[NSScrollView:0x100123ff0]-(NSSpace(20))-| (Names: '|':NSView:0x10012fdf0)>", 
"<NSLayoutConstraint:0x1001315d0 H:|-(NSSpace(20))-[NSScrollView:0x100123ff0] (Names: '|':NSView:0x10012fdf0)>") 

Will attempt to recover by breaking constraint 

frustratingly tyle miałem byłaby UI w wersji odbudowanej (który jest oparty na NSDocument aniżeli proste okno) Znowu uderzyłem w ten sam problem.

Jeśli ustawię translatesAutoResizingConstraints na NO w widokach podrzędnych, nie zostaną poprawnie rozplanowane. Ale te pod-widoki są złożone, więc nie jest to rozwiązanie, ponieważ moje okna nie są rozmieszczone. To jednak powstrzymuje wyjątek od rzucania.

Jeśli wyłączę funkcję AutoLayout w głównym oknie XIB opartym na NSDocument, to wyjątek również przestanie być zgłaszany. Ale wtedy układ elementów najwyższego poziomu jest nieprawidłowy, a pole nie ma właściwego rozmiaru. To nie jest tak skomplikowane, że nie mogłem ręcznie wyłożyć wszystkiego na zewnątrz.

Dziwna rzecz jest na mojej pierwszej wersji interfejsu, która działa bez żadnego rzutu. Pierwsza wersja ma zestaw Autolayout dla widoku najwyższego poziomu i wszystkich subviews.

Nie mogę dla mojego życia znaleźć tego, co niewyraźne ustawienie jest włączone w jednym, ale nie w drugim. Wkleiłem dokładnie ten sam kod, który działa w wersji okna do zamiany widoków na wersję opartą na dokumencie, i przejąłem kontrolę przez kontrolę sprawdzającą każde ustawienie.

Moją pamięcią o naprawieniu problemu po raz pierwszy jest to, że wyłączyłem AutoLayout na XIB, ale patrząc na to teraz próbuje naprawić po raz drugi, AutoLayout jest włączony i działa dobrze.

Pierwsza wersja działa - druga nie. Jedyne, co mogę wymyślić to to, że coś w NSDocument lub coś innego powoduje problem.

Jednak znalazłem sposób, aby to naprawić w przypadku numer dwa: wyłącz pole wyboru "AutoResizes Subviews" dla NSBox używanego jako kontener widoku.

Dlaczego to nie jest wymagane w pierwszej wersji interfejsu użytkownika (co działa dobrze z tym zestawem pól wyboru) jest zagadką.

W każdym razie - udokumentowane tutaj w przypadku, gdy pomaga komuś innemu.

Powiązane problemy