2014-09-23 10 views
24

Jestem w trakcie opracowywania aplikacji na iPhone'a i iPada. Obsługuje iOS6 i iOS7 i wykorzystuje wyłącznie układ automatyczny.Problemy z autolayoutem w iOS8 z kodem, który działa poprawnie w iOS7

W zeszłym tygodniu, gdy Apple ogłosił, że iOS8 jest gotowy na prime-time, uaktualniłem jeden z moich iPhone'ów i iPada zarówno do iOS8. Wpadłem też na XCODE do wersji 6. Mam drugiego iPhone'a, który zostawiłem na iOS7.

Wygenerowałem nowe pliki wykonywalne z Xcode 6 i byłem zestresowany, aby zobaczyć, że ich układy ekranów były pomieszane po uruchomieniu na moich urządzeniach z systemem iOS8, ale nadal dobrze na iOS7. Dotyczy to zarówno moich fizycznych urządzeń, jak i emulatorów Xcode.

Zajęło mi dużo kopania, ale jestem całkiem jasny teraz, co się dzieje, choć nie wiem dlaczego.

W szczególności, niektóre operacje automatycznego układu są dla mnie nieskuteczne w systemie iOS8, ale na iOS7 są dobre.

Niektóre przykłady obejmujące przycisk, który ja wprowadzania do bazowego widzenia, którego wielkość jest równa wielkości ekranu:

(1) Jeśli pytam układ automatycznego do położenia środkowego poziomą Buttona (CX) równa do poziomego środka leżącego u podstaw widoku, w wyniku czego poziome centrum przycisku znajduje się na lewej krawędzi leżącego u dołu widoku.

(2) Jeśli poprosię o automatyczny układ, aby szerokość przycisku była równa 50% szerokości widocznego pod nim widoku, nie ma on wcale żadnej szerokości.

jestem w stanie obejść te problemy w sposób następujący:

(1) Pytam układ automatycznego do pozycji środkowej przez Buttona równa lewej krawędzi bazowego widoku danych plus 50% szerokości ekranu.

(2) Pytam automatyczny układ, aby szerokość przycisku była równa 50% szerokości ekranu.

Powoli przechodzę swoją drogę, z takimi obejściami, z powrotem do kodu układu automatycznego, który działa dla mnie zarówno na iOS7, jak i iOS8. Ale naprawdę się zastanawiam, co tu się dzieje.

Wygląda na to, że układ automatyczny nie może określić rozmiaru podstawowego widoku, a więc obliczeń automatycznego układu, które wymagają, aby informacje się nie powiodły. Ale wie, gdzie znajdują się górna i lewa krawędź widoku, więc obliczenia oparte na tych danych kończą się sukcesem.

To jest duża aplikacja i napisałem setki linii kodu układu automatycznego dla iOS6 i iOS7, które działają idealnie dla mnie.

Od trzech dni robię poprawki i próbuję rzeczy z iOS8 i nie jestem mądrzejszy od samego początku, kiedy zaczynałem.

Ktoś ma jakieś sugestie lub przemyślenia, co może być problemem tutaj?

+0

Jestem na tej samej łodzi. W każdym razie wydaje się, że szerokość podrzędnego widoku wynosi 0, aby rozpocząć szerokość, dlatego kiedy powiedziałeś, że środek X przycisku jest centrum X widoku podstawowego, przycisk pojawia się na lewej krawędzi. – Zhang

+1

tak, a z tego, co widzę do tej pory, kiedy zaczynam umieszczać elementy sterujące na widoku, mogę użyć wszystkich różnych odmian relacji układu automatycznego między tymi kontrolkami. To znaczy, poziome centrum jednego przycisku może być wyrównane z innym bez problemów. – Gallymon

+0

Powinienem też wspomnieć, że nie używam IB. Cały mój kod układu automatycznego jest tworzony bezpośrednio przez konstrukcję NSLayoutConstraint/s. Zawsze robiłeś to w ten sposób i działało idealnie w iOS7. – Gallymon

Odpowiedz

3

Można znaleźć odpowiedź na to pytanie pomocne: UICollectionView cell subviews do not resize

W większości przypadków prace w iOS7 ale nie na iOS problemami układu 8 auto wydaje się wynikać z widoku głównego nie jest prawidłowo wielkości w iOS 8, szczególnie kiedy ustawimy translatesAutoresizingMaskIntoConstraints na NO. W przypadku moich widoków udało mi się ustawić ramkę widoku głównego w layoutSubviews (lub w zależności od tego, który inicjator ma odpowiednie ograniczenia), co rozwiązało problem.

self.contentView.frame = CGRectInset(self.bounds, 0, 0); 

Jak wynika z odpowiedzi powyżej, można również zrobić

self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; 

a następnie włącz translatesAutoresizingMaskIntoConstraints powrotem do NO przed rozpoczęciem ustawiania własnych ograniczeń w kodzie.

Zdecydowanie nie znoszę, że tak wiele naszych czasów jest podejmowanych z tymi denerwującymi potworami.

+0

Praneeth, dzięki za to. Próbowałem, ale nie ma to wpływu na problem, który mam. – Gallymon

+0

Hmm, przykro mi to słyszeć, ale to nie pomogło. W moim przypadku miałem mieszankę ograniczeń IB, a następnie korekt w kodzie w czasie wykonywania i to rozwiązało mój problem. Powodzenia. –

11

@robmayoff ma świetną odpowiedź na to: https://stackoverflow.com/a/26066992/1424669

Zasadniczo, w systemów iOS 8 nie można już nazwać setNeedsUpdateConstraints i setNeedsLayout na widoku i oczekują ograniczeń subviews, aby zaktualizować.

Musisz wywołać te metody na widoku, którego ograniczenie się zmienia. To jest wstecznie kompatybilne z iOS7.

PRZYKŁAD:

Załóżmy, że masz ViewController z widoku głównego self.view i podrzędny o nazwie containerView. containerView ma dołączone do niego NSLayoutConstraint, które chcesz zmienić (w tym przypadku najwyższą spację).

W iOS7 można zaktualizować wszystkie ograniczenia w VC żądając nowy układ do widoku głównego:

self.containerView_TopSpace.constant = 0; 
[self.view setNeedsUpdateConstraints]; 
[self.view setNeedsLayout]; 

W systemów iOS 8 trzeba zwrócić układy na containerView:

self.containerView_TopSpace.constant = 0; 
[self.containerView setNeedsUpdateConstraints]; 
[self.containerView setNeedsLayout]; 
+0

BFar, to dobra wiadomość i ma sens. Nie mogę się doczekać, kiedy go wypróbuję i zobaczę, czy mogę rozwiązać ten problem. – Gallymon

+0

@BFar Czy możesz złożyć prosty przykładowy projekt, który demonstruje ten problem (np. Działa na 7 SDK, ale nie na 8 SDK), a następnie złożyć radar i udostępnić radar #? – smileyborg

+0

BFar, próbowałem pomysłów robmayoff, ale nie wydają mi się one powiązane z moim problemem. Mam teraz obejście prawne, więc naciskam. Dzięki! – Gallymon

0

W mój przypadek, problem związany z ograniczeniami oznaczonymi UIView-Encapsulated-Layout-Width i UIView-Encapsulated-Layout-Height. Kiedy je usunąłem, wszystko zachowywało się tak, jakby mój widok był zerowy, a wszystko wyśrodkowane w lewym górnym rogu ekranu. Kiedy je zostawiłem, nowe ograniczenia zadziałały zgodnie z oczekiwaniami. Zachowałem również ograniczenia oznaczone jako _UILayoutSupportConstraint.

Powiązane problemy