Odkryłem dziwne zachowanie w mojej aplikacji, w której podłączony IBOutlet
ma ramkę widoku połączonego między wywołaniami w moim kontrolerze widoku do viewWillAppear:
i viewDidAppear:
. Oto odpowiedni kod w mojej UIViewController
podklasie:
-(void)viewWillAppear:(BOOL)animated {
NSLog(@"%@", self.scrollView);
}
-(void)viewDidAppear:(BOOL)animated {
NSLog(@"%@", self.scrollView);
}
i wynikowy wynik dziennika:
MyApp[61880:c07] <UIScrollView: 0x1057eff0; frame = (0 0; 0 0); clipsToBounds = YES; autoresize = TM+BM; gestureRecognizers = <NSArray: 0x10580100>; layer = <CALayer: 0x1057f210>; contentOffset: {0, 0}>
MyApp[61880:c07] <UIScrollView: 0x1057eff0; frame = (0 44; 320 416); clipsToBounds = YES; autoresize = TM+BM; gestureRecognizers = <NSArray: 0x10580100>; layer = <CALayer: 0x1057f210>; contentOffset: {0, 0}>
Co wyraźnie pokazuje, że ramka zmienia się między dwoma wywołaniami. Chciałem zrobić konfigurację z widokiem w viewDidLoad
metodzie, ale jeśli zawartość nie jest dostępna do zmiany, dopóki nie pojawi się na ekranie, wydaje się to całkiem bezużyteczne. Co mogło się dziać?
iphone
ios
objective-c
uiscrollview
Jumhyn
źródło
źródło
viewDidLayoutSubviews
była właściwą drogą. Musiałem po prostu umieścić całą moją zawartość w podglądzie, aby metoda nie była ponownie wywoływana za każdym razem, gdy zmieniłem ramkę widoku głównego.Odpowiedzi:
Autolayout
dokonał ogromnej zmiany w sposobie projektowania i rozwijania GUI naszych widoków. Jedną z głównych różnic jest to, żeautolayout
nie zmienia rozmiarów naszego widoku natychmiast, ale tylko wtedy, gdy jest uruchamiany, to znaczy w określonym czasie, ale możemy zmusić go do natychmiastowego ponownego obliczenia naszych ograniczeń lub oznaczyć je jako „wymagające” układu. Działa jak-setNeedDisplay
.Dużym wyzwaniem było dla mnie zrozumienie i zaakceptowanie tego, że nie musimy już używać masek autorezowania, a rama stała się bezużyteczną właściwością w umieszczaniu naszych widoków. Nie musimy już myśleć o położeniu widoku, ale powinniśmy pomyśleć, jak chcemy je widzieć w powiązanej ze sobą przestrzeni.
Kiedy chcemy połączyć starą maskę autorezowania i autoukład, pojawiają się problemy. Już niedługo powinniśmy pomyśleć o wdrożeniu autoukładu i starać się unikać mieszania starego podejścia w hierarchii widoków opartej na autoukładzie.
Dobrze jest mieć widok kontenera, który używa tylko masek autorealizacji, takich jak widok główny kontrolera widoku, ale jest lepszy, jeśli nie próbujemy mieszać.
Nigdy nie korzystałem ze scenorysu, ale najprawdopodobniej jest poprawny. Korzystając z funkcji Autolayout, ramki widoków są ustawiane, gdy silnik autoukładu rozpoczyna obliczenia. Spróbuj zapytać o to samo zaraz po super
- (void)viewDidLayoutSubviews
metodzie kontrolera widoku.Ta metoda jest wywoływana, gdy mechanizm automatycznego układania zakończy obliczanie ramek widoków.
źródło
add something on a screen, "just before it appears to the user". The actual answer is indeed to use viewDidLayoutSubviews.
... będziesz pokazywał ten widok wiele razyZ dokumentacji:
Powiadamia kontroler widoku, że jego widok ma zostać dodany do hierarchii widoków.
Powiadamia kontroler widoku, że jego widok został dodany do hierarchii widoków.
W rezultacie klatki podglądów podrzędnych nie są jeszcze ustawione w
viewWillAppear
:Odpowiednią metodą modyfikacji interfejsu użytkownika przed wyświetleniem widoku na ekranie jest:
Powiadamia kontroler widoku, że jego widok właśnie przedstawił widoki podrzędne.
źródło
viewDidLayoutSubviews
będzie wywoływany wiele razy i nie zawsze z tą samą ramką (myślę, że czasami jest wywoływany z CGRectZero przy pierwszym wywołaniu). Jest wywoływana przy każdym dodanym widoku podrzędnym i innych zmianach w widoku.połączenie
w swojej
viewWillAppear
metodzie. Następnie możesz uzyskać dostęp do jego ramki i będzie miała taką samą wartość, jak w przypadku drukowaniaviewDidAppear
źródło
W moim przypadku przeniesienie wszystkich metod związanych z ramką do
działało idealnie (próbowałem zmodyfikować ograniczenia z storyboardu).
źródło