ViewWillAppear: ve viewDidAppear arasındaki çerçeve değişikliklerini görüntüleyin:


85

Uygulamamda, IBOutletbağlantılı bir görünümün çerçevesinin, görünüm denetleyicimdeki viewWillAppear:ve arasındaki aramalar arasında bulunduğu garip bir davranış keşfettim viewDidAppear:. İşte UIViewControlleralt sınıfımdaki ilgili kod :

-(void)viewWillAppear:(BOOL)animated {
    NSLog(@"%@", self.scrollView);
}

-(void)viewDidAppear:(BOOL)animated {
    NSLog(@"%@", self.scrollView);
}

ve ortaya çıkan günlük çıktısı:

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}>

Bu, çerçevenin iki arama arasında değiştiğini açıkça gösteriyor. viewDidLoadYöntemdeki görünümle kurulum yapmak istedim , ancak içeriği ekrana gelene kadar değiştiremem mümkün değilse, bu oldukça işe yaramaz görünüyor. Ne olabilir?


2
Otomatik düzen kullanıyor musunuz? Bu görünümü Arayüz oluşturucuya mı yoksa programlı olarak mı ekliyorsunuz?
Andrea

Otomatik düzen etkinleştirilir ve bu görünüm bir film şeridinden IB'de oluşturulur.
Jumhyn

1
Hiç storyboard kullanmadım, ama büyük olasılıkla doğru. Görünümlerinizin Otomatik Düzen çerçevesini kullanma, otomatik düzen motoru hesaplamaya başladığında ayarlanır. Görünüm denetleyicinizin süper - (void) viewDidLayoutSubviews yönteminden hemen sonra aynı şeyi sormaya çalışın.
Andrea

Bu, etkinliğimi doğru zamanda başarıyla tetikler, ancak bu yöntem, görünümde herhangi bir animasyon gerçekleştirdiğimde de çağrılır.
Jumhyn

1
viewDidLayoutSubviewsdoğru yol buydu. Ana görünümün çerçevesini her değiştirdiğimde yöntemin yeniden çağrılmaması için tüm içeriğimi bir alt görünüme yerleştirmek zorunda kaldım.
Jumhyn

Yanıtlar:


112

Autolayoutgörüşlerimizin GUI'sini tasarlama ve geliştirme şeklimizde büyük bir değişiklik yaptık. Temel farklardan biri, autolayoutgörünüm boyutumuzu hemen değiştirmemesi, ancak yalnızca tetiklendiğinde, bu belirli bir zamanda anlamına gelir, ancak kısıtlamalarımızı hemen yeniden hesaplamaya veya onları düzene "ihtiyaç var" olarak işaretlemeye zorlayabiliriz. Gibi çalışır -setNeedDisplay.
Benim için en büyük zorluk, artık otomatik yeniden boyutlandırma maskeleri kullanmamıza gerek olmadığını ve çerçevenin görüşlerimizi yerleştirmede işe yaramaz bir özellik haline geldiğini anlamak ve kabul etmekti. Artık görüş konumunu düşünmemize gerek yok ama birbirimizle ilişkili bir alanda onları nasıl görmek istediğimizi düşünmeliyiz.
Eski otomatik yeniden boyutlandırma maskesini ve otomatik düzeni karıştırmak istediğimizde, sorun çıktığı zamandır. Otomatik düzen uygulamasını çok yakında düşünmeli ve eski yaklaşımı otomatik düzeni temel alan bir görünüm hiyerarşisinde karıştırmamaya çalışmalıyız.
Bir görünüm denetleyicisinin ana görünümü gibi yalnızca otomatik yeniden boyutlandırma maskeleri kullanan bir kap görünümüne sahip olmak iyidir, ancak karıştırmaya çalışmazsak daha iyidir.
Hiç storyboard kullanmadım, ama büyük olasılıkla doğru. Otomatik Düzen kullanıldığında, görünümlerinizin çerçevesi, otomatik düzen motoru hesaplamaya başladığında ayarlanır. - (void)viewDidLayoutSubviewsGörüntü denetleyicinizin süper yönteminden hemen sonra aynı şeyi sormaya çalışın .
Bu yöntem, görünümlerinizin çerçevelerini hesaplamak için otomatik düzen motoru bittiğinde çağrılır.


6
- (void) viewDidLayoutSubviews benim için cevaptır! Çok teşekkürler!
FrizzTheSnail

Bu cevap gerçekten doğru değil. Evet, tabii ki, (5?) Yıldır artık otomatik düzen kullanmak zorundasınız. Ancak , "kullanıcıya görünmeden hemen önce" ekrana bir şey eklemeniz gereken ( otomatik düzen kullanılarak ) çok sayıda durum vardır . (Bunu viewDidAppear'da yaparsanız bir titreme alırsınız. Bunu viewWillAppear'da yaparsanız, konumlar yanlış olacaktır.) Asıl cevap aslında viewDidLayoutSubviews'i kullanmaktır.
Fattie

add something on a screen, "just before it appears to the user". The actual answer is indeed to use viewDidLayoutSubviews.... bu manzarayı birçok kez göstereceksiniz
Andrea

156

Gönderen belgeler:

viewWillAppear:

Görünüm denetleyicisine, görünümünün bir görünüm hiyerarşisine eklenmek üzere olduğunu bildirir.

viewDidAppear:

Görünüm denetleyicisine, görünümünün bir görünüm hiyerarşisine eklendiğini bildirir.

Sonuç olarak, alt görünümlerin çerçeveleri şunlarda henüz ayarlanmamıştır viewWillAppear:

Görünüm ekrana sunulmadan önce kullanıcı arayüzünüzü değiştirmek için uygun yöntem şudur:

viewDidLayoutSubviews

Görünüm denetleyicisine, görünümünün alt görünümlerini henüz ortaya koyduğunu bildirir.


2
Ugh, bu can sıkıcı. Belgelerin ifadesi bile sanki viewWillApepar: ve viewDidAppear: birbiri ardına gerçekleşecekmiş gibi görünmesini sağlar.
Jumhyn

2 ay bu cevabı bekliyorum ... teşekkürler buldum !! ÇOK TEŞEKKÜR EDERİM!
Rafael Ruiz Muñoz

6
Her viewDidLayoutSubviewszaman aynı çerçeve ile değil birden çok kez çağrılacağına dikkat edilmelidir (bazen ilk çağrıda CGRectZero ile çağrıldığını düşünüyorum). Görünümdeki her eklenen alt görünüm ve diğer değişiklikler için çağrılır.
bauerMusic

Bütün gün buna karıştırıyorum (viewDidLayoutSubviews, görünümü kapatırken de dahil olmak üzere birden çok kez çağrılıyor) ve onunla ef'i söyledim ve mantığı bir if ifadesine koydum ve sonra doğru olacak bir bool yaptım kod bir kez çalıştı. Bence daha temiz bir yol olmalı, ama çok fazla zaman geçti.
solenoid

bunun temeline inmeliyiz! viewDidLayoutSubviews korkunç, seNeedDisplay çalışmıyor
Yaro

9

aramak

self.scrollView.layoutIfNeeded ()

senin içinde viewWillAppearyöntemle. Daha sonra çerçevesine erişebilirsiniz ve yazdırdığınızla aynı değere sahip olacaktır.viewDidAppear


1
Hayır, bu doğru değil. Örnek: Ekranda bir gezinme çubuğunuz var (nav denetleyicinizden). LayoutIfNeeded () öğesinden sonra bile gezinti çubuğunun yüksekliği dahil edilmediğinden çerçeve boyutunuz değişecektir.
xaphod

Bu , kaydırma görünümü çerçevesi boyutunun yeniden hesaplanmasını zorlamanın iyi bir yoludur, böylece scrollView çerçevesi denetim görünümü içindeki kısıtlamalara bağlıysa, görünüm düzeni çağrı hiyerarşisi boyunca tutarlı olur.
smakus

4

Benim durumumda, çerçeveyle ilgili tüm yöntemleri

override func viewWillLayoutSubviews()

mükemmel çalıştı (film şeridindeki kısıtlamaları değiştirmeye çalışıyordum).

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.