ViewWillAppear के बीच फ़्रेम परिवर्तन देखें: और viewDidAppear:


85

मैंने अपने एप्लिकेशन में एक अजीब व्यवहार की खोज की है, जहां एक कनेक्टेड के IBOutletपास मेरे व्यू कंट्रोलर में कॉल के बीच जुड़ा हुआ व्यू फ्रेम है viewWillAppear:और viewDidAppear:। यहाँ मेरे UIViewControllerउपवर्ग में प्रासंगिक कोड है :

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

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

और परिणामी लॉग आउटपुट:

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

जो स्पष्ट रूप से दिखाता है कि दो कॉल के बीच फ्रेम बदल रहा है। मैं viewDidLoadविधि में दृश्य के साथ सेटअप करना चाहता था , लेकिन अगर सामग्री मेरे लिए स्क्रीन पर आने तक बदलने के लिए उपलब्ध नहीं है, तो यह बहुत बेकार लगता है। क्या हो सकता है?


2
क्या आप ऑटोलेयूट का उपयोग कर रहे हैं? क्या आप इंटरफ़ेस बिल्डर या प्रोग्राम में इस दृश्य को जोड़ रहे हैं?
एंड्रिया

Autolayout सक्षम है, और यह दृश्य एक स्टोरीबोर्ड से IB में बनाया गया है।
जुम्हिन

1
मैंने कभी भी स्टोरीबोर्ड का इस्तेमाल नहीं किया, लेकिन ज्यादातर यह सही है। ऑटोलयूट इंजन अपनी गणना शुरू करने पर अपने विचारों के ऑटोलेयआउट फ्रेम का उपयोग करना निर्धारित करता है। सुपर - (शून्य) के दृश्य के ठीक बाद वही बात पूछने की कोशिश करें जो आपके व्यू कंट्रोलर का एमपीथोड है।
एंड्रिया

यह सही समय पर मेरे ईवेंट को सफलतापूर्वक ट्रिगर करता है, लेकिन जब भी मैं दृश्य पर कोई भी एनीमेशन करता हूं, तो उस पद्धति को भी कहा जाता है।
जुम्हिन

1
viewDidLayoutSubviewsजाने का सही तरीका था। मुझे बस अपनी सभी सामग्री को एक सबव्यू में डालना था ताकि जब भी मैं मुख्य दृश्य के फ्रेम को बदलूं, तो विधि को फिर से नहीं बुलाया जा सके।
जुम्हिन

जवाबों:


111

Autolayoutहमने अपने विचारों के GUI को कैसे डिजाइन और विकसित किया है, इसमें बहुत बड़ा बदलाव किया है। मुख्य अंतरों में से एक यह है कि autolayoutहमारे दृश्य आकारों को तुरंत नहीं बदला जाता है , लेकिन केवल जब ट्रिगर किया जाता है, तो इसका मतलब है कि एक विशिष्ट समय पर, लेकिन हम इसे अपने बाधाओं को तुरंत हटाने या लेआउट की "आवश्यकता के रूप में" चिह्नित करने के लिए मजबूर कर सकते हैं। यह काम करता है -setNeedDisplay
मेरे लिए बड़ी चुनौती यह समझने और स्वीकार करने की थी कि, हमें अब ऑटोरेस्सिगिंग मास्क का उपयोग करने की आवश्यकता नहीं है, और फ्रेम हमारे विचार रखने में एक बेकार संपत्ति बन गई है। हमें अब दृश्य स्थिति के बारे में सोचने की आवश्यकता नहीं है, लेकिन हमें यह सोचना चाहिए कि हम उन्हें एक-दूसरे से संबंधित स्थान में कैसे देखना चाहते हैं।
जब हम पुराने ऑटोरेस्सिगिंग मास्क को मिलाना चाहते हैं और समस्या उत्पन्न होने पर ऑटोलैयट होता है। हमें वास्तव में जल्द ही ऑटोलेयूट कार्यान्वयन के बारे में सोचना चाहिए और ऑटोलआउट के आधार पर एक दृश्य पदानुक्रम में पुराने दृष्टिकोण को मिश्रण करने से बचने की कोशिश करनी चाहिए।
एक कंटेनर दृश्य होना ठीक है जो केवल ऑटोरेस्पिरिंग मास्क का उपयोग करता है, जैसे कि एक दृश्य नियंत्रक का मुख्य दृश्य, लेकिन बेहतर है अगर हम मिश्रण करने की कोशिश नहीं करते हैं।
मैंने कभी भी स्टोरीबोर्ड का इस्तेमाल नहीं किया, लेकिन ज्यादातर यह सही है। ऑटोलाययूट का उपयोग करके, आपके विचारों के फ्रेम को तब सेट किया जाता है जब ऑटोलेयूट इंजन इसकी गणना शुरू करता है। - (void)viewDidLayoutSubviewsअपने व्यू कंट्रोलर की विधि के सुपर के ठीक बाद वही बात पूछने की कोशिश करें ।
इस पद्धति को तब कहा जाता है जब ऑटोलयूट इंजन आपके विचारों के फ्रेम की गणना करने के लिए समाप्त हो गया है।


5
- (शून्य) viewDidLayoutSubviews मेरे लिए जवाब है! आपका बहुत बहुत धन्यवाद!
१२:५२ पर फ्रिज़इन्सनैल

यह उत्तर वास्तव में सही नहीं है। हां, जाहिर है, (5?) वर्षों के लिए अब आपको ऑटोलाययूट का उपयोग करना होगा। लेकिन किसी भी संख्या में स्थितियां हैं ( ऑटोलैयूट का उपयोग करके ) जहां आपको स्क्रीन पर कुछ जोड़ने, कहने की ज़रूरत है, "उपयोगकर्ता के सामने आने से ठीक पहले"। (यदि आप इसे viewDidAppear में करते हैं तो आपको एक झिलमिलाहट मिल जाएगी। यदि आप इसे viewWillAppear में करते हैं - स्थिति गलत होगी।) वास्तविक उत्तर वास्तव में viewDidLayoutSubviews का उपयोग करना है।
फेटी

add something on a screen, "just before it appears to the user". The actual answer is indeed to use viewDidLayoutSubviews.... आप यह दिखाने जा रहे हैं कि बहुत बार देखें
एंड्रिया

156

से प्रलेखन:

viewWillAppear:

दृश्य नियंत्रक को सूचित करता है कि इसका दृश्य दृश्य पदानुक्रम में जोड़ा जाने वाला है।

viewDidAppear:

दृश्य नियंत्रक को सूचित करता है कि इसका दृश्य दृश्य पदानुक्रम में जोड़ा गया था।

परिणामस्वरूप सबव्यू के फ्रेम अभी तक इसमें सेट नहीं हुए हैं viewWillAppear:

स्क्रीन पर दृश्य प्रस्तुत करने से पहले अपने UI को संशोधित करने की उपयुक्त विधि है:

viewDidLayoutSubviews

दृश्य नियंत्रक को सूचित करता है कि इसका दृश्य अभी इसके साक्षात्कारों को निर्धारित करता है।


2
उह, यह कष्टप्रद है। यहां तक ​​कि प्रलेखन के शब्दांकन से ऐसा लगता है जैसे कि viewWillApepar: और viewDidAppear: एक दूसरे के साथ सीधे होना चाहिए।
जुमहिन

2 महीने के इस जवाब का इंतज़ार ... धन्यवाद मुझे मिल गया !! आपका बहुत बहुत धन्यवाद!
राफेल रुइज मुनोज

6
ध्यान दिया जाना चाहिए कि viewDidLayoutSubviewsकई बार कहा जाएगा और हमेशा एक ही फ्रेम के साथ नहीं, (मुझे लगता है कि इसे CGRectZero के साथ पहले कभी-कभी कहा जाता है)। इसे प्रत्येक जोड़े गए सबव्यू और दृश्य में अन्य परिवर्तनों के लिए बुलाया जाता है।
बॉउम्यूजिक

मैं इस पूरे दिन (butDidLayoutSubviews दृश्य को खारिज करते हुए, सहित कई बार कॉल किया जा रहा है) में ब्यूटि कर रहा हूं, और बस इसके साथ एफई ने कहा, और तर्क को एक बयान में डाल दिया और एक बूल बनाया, जो सच के बाद सेट हो जाता है कोड एक बार चला है। मुझे लगता है कि एक क्लीनर तरीका होना चाहिए, लेकिन बहुत समय पहले ही इसमें डूब गया।
solenoid

हमें इस की तह तक पहुँचना है! ViewDidLayoutSubviews भयानक है, seNeedDisplay काम नहीं करता है
यारो

9

कॉल

self.scrollView.layoutIfNeeded ()

आपकी viewWillAppearविधि में। बाद में आप इसे फ्रेम में एक्सेस कर सकते हैं और आपके प्रिंट करते ही इसका मान होगाviewDidAppear


1
नहीं, यह सही नहीं है। उदाहरण: आपके पास स्क्रीन पर एक नेविगेशन बार है (अपने नौसेना नियंत्रक से)। लेआउटआईफाइड () के बाद भी, नेवबार की ऊंचाई शामिल नहीं है, इसलिए आपके फ्रेम का आकार बदल जाएगा।
xaphod

यह है एक अच्छा तरीका इतना है कि यह दृश्य लेआउट कॉल पदानुक्रम में एक जैसा है scrollview फ्रेम अपने superview भीतर की कमी से जुड़ा हुआ है, तो एक scrollview फ्रेम आयाम की एक फिर से गणना के लिए मजबूर करने।
स्मैकस

4

मेरे मामले में, सभी फ्रेम संबंधित तरीकों को आगे बढ़ाना

override func viewWillLayoutSubviews()

पूरी तरह से काम किया (मैं स्टोरीबोर्ड से बाधाओं को संशोधित करने की कोशिश कर रहा था)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.