2015-09-02 12 views
5

Próbując przełamać problem, który miałem na chwilę sięJak określić rozmiar UIView przed viewDidAppear jego ViewController

Tło

Załóżmy, staram się obliczyć UIImage który powinien idealnie pasować do UIImageView, który jest ułożony z ograniczeniami w serii ujęć.

Zawartość obrazu nie powinna być wypełniona/dopasowana do kształtu obrazu, ale idealnie pasować do ramki. Dlatego mam metodę w moim viewController

- (UIImage *)calculatedImageForRect:(CGRect)imageRect 

Problem

Chcę się upewnić, że ImageView zawiera już prawidłowy obraz tak szybko jak widok staje się widoczne, tak również w prosty push przejście. Ponadto nie chcę generować UIImage wiele razy, ponieważ jest stosunkowo droga.

Staje się to szczególnie interesujące z urządzeń takich jak iPhone6 ​​Plus, które mają inną rozdzielczość ekranu

Oczywiście w viewDidLoad ramki nie są ustawione poprawnie. W tym momencie ramki są ustawione tak, jak w podglądzie scenorysu - np. konfiguracja do reprezentowania rozdzielczości IPhone5. To samo dotyczy viewWillAppear. Tutaj ramka będzie np. być (10,10,300,100) < - nazwijmy to źle ramy

Na viewDidAppear rama jest prawidłowe (10,10,394,100) = z poprawne kadrów < - zamiast 320 punktów szerokości, iPhone6Plus ma 414 punktów. Niemniej jednak tutaj jest już za późno, ponieważ widok jest już widoczny, a ustawienie obrazu spowodowałoby migotanie (pusty obraz> nowy wygenerowany obraz).

wiem właściwy czas, aby pracować z szerokością jest viewDidLayoutSubviews, który nazywany jest pierwszy z niewłaściwym ramki przynajmniej raz, a potem w pewnym momencie z właściwej ramki. Ale jak już mówiłem, nie chcę do generowania obrazu wiele razy, więc tu jest dylemat:

Jak mogę określić prawą ramkę zanim będzie widoczny?

Oczywiście mogę obliczyć właściwą ramkę z uchwałą [UIScreen mainScreen] poprzez współpracę z tylnym & wiodących ograniczeń UIImageView, ale czuje się brudna.

+0

Tak więc istotą pytania jest to, że chcesz dowiedzieć się, jak otrzymać powiadomienie, gdy określony widok w hierarchii widoku (w tym przypadku UIImageView) jest ostatecznie ustawiony na poprawną ramkę, ale przed renderowaniem na ekranie? – algal

+0

Tak, to jest dokładnie to, co chcę wiedzieć. – MarkHim

Odpowiedz

7

Powodem, dla którego nie można użyć numeru viewDidLayoutSubviews, jest to, że można go nazwać więcej niż raz. Dotyczy to również layoutSubviews.

Dlaczego tak jest? Jednym z powodów jest to, że ponieważ układ oparty na ograniczeniach jest procesem iteracyjnym, który może obejmować wiele przebiegów. Na przykład powiedzmy, że wymuszam układ widoku V, który zawiera w swojej hierarchii widoku subview W, który zawiera widok podrzędny X. Pierwsze obliczenia Auto Layout układu X mogą zmienić ograniczenia, które następnie wymagają ponownego obliczenia W , który następnie wymaga ponownego obliczenia X.Zasadniczo w przeciwieństwie do układu z automatycznymi maskami zmiany rozmiaru, który jest z góry do dołu, tak aby widok zewnętrzny zawsze określał układ jego podglądu.

Jednakże, I wierzę w(ale nie jestem w 100% pewny), że jeśli cały kod układu zostanie poprawnie zaimplementowany, to te wielokrotne przebiegi układu powinny mieć miejsce w ciągu jednego obrotu pętli. Oznacza to, że po uruchomieniu tego procesu przez wywołanie layoutIfNeeded w celu wymuszenia układu na V, możesz być pewny, że wszystkie układy Auto Layout przechodzą na W i X zakończyły, po powrocie layoutIfNeeded. Brak znaczników "potrzeby" lub "wymaga aktualizacji ograniczenia" pozostanie nieczytelny, czekając na następny obrót bieżącej pętli, aby zakończyć pracę.

Może to wskazywać drogę do rozwiązania. Jeśli wymusisz wczesny układ widoku najwyższego poziomu w hierarchii (takiego jak widok główny kontrolera widoku, do którego przechodzisz), to po przejściu tego layoutu UIImageView będzie mieć poprawną ramkę i możesz tego użyć ramka do generowania obrazu.

Zasadniczo, zamiast wykonywać układ w ostatnim możliwym momencie, zmuszasz go do zrobienia wcześniej. Wtedy możesz wiedzieć, kiedy to się skończy, ponieważ zainicjowałeś i widzisz koniec procesu, czekając aż layoutIfNeeded wyjdzie. A następnie możesz obserwować wynikową wartość, na której Ci zależy.

+1

Szczerze mówiąc, nie spodziewałem się, że to zadziała - ale tak jest. Nazywam 'layoutIfNeeded' w' viewWillAppear: 'teraz i zgodnie z opisem, wszystkie subviews są układane poprawnie później. Dziękuję Ci za odpowiedź. – MarkHim

+0

Żyję, aby służyć. – algal