2010-07-07 13 views
9

मेरे पास एक नेविगेशन नियंत्रक है। विचारों में से एक अपने viewDidAppear: में कस्टम सबव्यूव जोड़ता है। मैंने देखा कि पहली बार जब मैं ऐप लॉन्च करने के बाद इस व्यू कंट्रोलर के उदाहरण पर नेविगेट करता हूं, viewDidAppear: दो बार आमंत्रित करता है। अगर मैं इस दृश्य को ढेर से पॉप करता हूं और फिर से नेविगेट करता हूं, viewDidAppear: प्रति उपस्थिति केवल एक बार आमंत्रित करता है। बाद के सभी उपस्थिति एक बार viewDidAppear: का आह्वान करते हैं।viewDidAppear को एक ही उदाहरण पर दो बार बुलाया जाता है, लेकिन पहली बार यह वर्ग लोड होता है NIB

मेरे लिए समस्या यह है कि पहली बार जब मैं इस विचार को प्राप्त करता हूं तो मैं सब्यूव्यू की संख्या से दोगुना हो जाता हूं। मैं फ्लैग वैरिएबल या कुछ ऐसे लोगों को पेश करके इस समस्या के आसपास काम करता हूं, लेकिन मैं समझना चाहता हूं कि क्या हो रहा है और इन परिस्थितियों में मुझे दो आमंत्रण कैसे मिलते हैं।

उत्तर

14

आपको कभी भी -viewWillAppear:/-viewDidAppear: पर भरोसा नहीं करना चाहिए जिसे गायब रूपों के साथ उचित रूप से संतुलित कहा जाता है। जबकि सिस्टम व्यू कंट्रोलर हमेशा कॉल को सही तरीके से ब्रैकेट करने के लिए सबसे अच्छा कर सकते हैं, मुझे नहीं पता कि वे कभी इसकी गारंटी देते हैं, और निश्चित रूप से जब कस्टम व्यू कंट्रोलर का उपयोग करते हैं तो आप उन स्थितियों को पा सकते हैं जहां इन्हें कई बार कहा जा सकता है।

संक्षेप में, अपने -viewWillAppear:/-viewDidAppear: तरीकों, idempotent किया जाना चाहिए जिसका अर्थ है यदि -viewDidAppear: अपने नियंत्रक पर लगातार दो बार कहा जाता है, यह ठीक से व्यवहार करना चाहिए। यदि आप कस्टम दृश्य लोड करना चाहते हैं, तो आप इसे -viewDidLoad में ऐसा करना चाहेंगे और फिर -viewDidAppear: में केवल ऑन-स्क्रीन (यदि वे पहले से नहीं हैं) डाल दें।

आप अपने -viewDidAppear: विधि में ब्रेकपॉइंट भी डाल सकते हैं यह देखने के लिए कि इसे पहली बार दिखाया जाने वाला दो बार क्यों कहा जा रहा है।

+0

मेरे पास 'viewDidAppear: 'में एक ब्रेकपॉइंट है। यह सवाल क्यों जवाब दे सकता है? – iter

+0

यह पता लगाने के लिए कि सिस्टम इस विधि को क्यों कॉल कर रहा है, स्टैक ट्रेस को देखें। यदि दोनों कॉल के लिए बैकट्रैक अलग है, तो आप इसका उपयोग करके यह पता लगाने के लिए इसका उपयोग कर सकते हैं कि क्या हो रहा है। बैकट्रैस में जो भी है, उसके आधार पर यह उपयोगी हो सकता है या नहीं भी हो सकता है। –

+0

ढेर समान दिखते हैं, इसलिए आपके सुझाव पर मेरा आश्चर्य है। मेरा समाधान कोड को दोबारा करने के लिए है ताकि मैं 'viewDidAppear:' पर ​​कोड को अप्रत्यक्ष रूप से 'viewDidLoad:' से कॉल कर सकूं, और इसलिए पूरे मुद्दे से बचें। मैं आपका जवाब स्वीकार कर रहा हूं भले ही डबल इनवोकेशन अभी भी मेरे लिए एक रहस्य है। Idempotent शब्द का उपयोग करने के लिए – iter

1

शायद आप viewDidLoad (या कुछ अन्य सामान वहां जा रहे हैं) में viewDidAppear का आह्वान करते हैं, क्योंकि यह स्मृति से दृश्य लोड करने के दौरान केवल एक बार बुलाया जाता है। यह मैच होगा, कि यह केवल पहली बार दो बार बुलाया गया है।

+0

यही तो मेरा पहला विचार था। लेकिन नहीं, मैं ऐसा नहीं कर रहा हूं। और यदि मैंने 'viewDidAppear:' आमंत्रण को देखने के लिए ब्रेकपॉइंट सेट किया है, तो इसमें से कोई भी मेरी विधियां इसमें दिखाई नहीं दे रही हैं। – iter

0

आपको निश्चित रूप से अधिक जानकारी प्रदान करनी चाहिए।

क्या यह मूल दृश्य नियंत्रक है?
हो सकता है कि आप इस रूट व्यू कंट्रोलर के साथ नेविगेशन कंट्रोलर शुरू करें और फिर इसे नेविगेशन कंट्रोलर पर फिर से दबाएं?

+0

दिलचस्प विचार, लेकिन नहीं, मैं इसे दो बार धक्का नहीं दे रहा हूं। मैं 'एनएसएलओजी (@"% @ ", [[स्वयं नेविगेशन नियंत्रक] व्यू कंट्रोलर]);' viewDidAppear' से 'और रूट व्यू के शीर्ष पर बैठे मेरे दृश्य का एक उदाहरण देखें। – iter

+0

शायद आपके पास गलती से 2 नेविगेशन नियंत्रक हैं? –

0

एक और समाधान जो आपके अंतर्निहित कारण हो सकता है: सुनिश्चित करें कि आप अपने viewWillAppear: विधि के भीतर से कोई भी नया दृश्य नियंत्रक प्रस्तुत नहीं कर रहे हैं।

मैं बुला रहा था:

[appDel.window.rootViewController presentViewController:login animated:YES completion:nil]; 

viewWillAppear के भीतर से और मेरी प्रारंभिक देखकर कुलपति viewDidAppear: पद्धति के रूप में आप का उल्लेख ही स्टैक ट्रेस साथ दो बार क्रमिक कहा जाता है।और viewDidDisappear:

करने के लिए कोई मध्यस्थ कॉल उद्भव कुलपति viewDidAppear: विधि डबल-कॉल मुद्दे को मंजूरी दे दी के लिए presentViewController: चलती है, और इसलिए अब प्रवाह है:

  1. मूल viewDidAppear: बुलाया
    • कॉल presentViewController यहाँ
  2. मूल viewDidDisappear:
  3. नए दृश्य प्रस्तुत किया है और अब मुझे एक चेतावनी के बारे में "unbalanced VC display"

इस जवाब की मदद से फिक्स्ड देता है: https://stackoverflow.com/a/13315360/1143123 हल करने "Unbalanced calls to begin/end appearance transitions for ..."

0

यह नहीं था एक iOS 5 बग, लेकिन एक छिपे हुए व्यवहार का प्रयास करते समय addChildViewController का:। मैं प्रलेखन की कमी के लिए एक रडार दर्ज करनी चाहिए, मुझे लगता है कि https://github.com/defagos/CoconutKit/issues/4

-1

यह इस तरह एक कष्टप्रद बात नहीं, आप इसे एक बार चलाता है लेकिन फिर मैं अब जो हिंसा का कारण है इस बारे में पता चला लगता है कि है ... यह सब पर लागू होता है 3 (ViewDidAppear, ViewDidLoad, और ViewWillAppear), मुझे भुगतान टर्मिनल के साथ एकीकृत करते समय यह मिल रहा है; एक बार यह एपीआई को कॉल करने के बाद, विंडो को फिर से लोड किया जा रहा है जब यह पहले से स्क्रीन पर है और इसकी सभी मेमोरी अभी भी है (बनाए रखा नहीं है)।

मैं सभी दिनचर्या उपर्युक्त निम्न कार्य करके इसका समाधान नहीं होता, नीचे दिए गए उनमें से एक के लिए एक नमूना है:

BOOL viewDidLoadProcessed = false; 

-(void)viewDidLoad:(BOOL)animated 
{ 
    if (!viewDidLoadProcessed) 
    { 
     viewDidLoadProcessed = YES; 
     . 
     . 
     . 
     ... do stuff here... 
     . 
     . 
    } 
} 

दोहराएँ सभी अन्य दो के लिए ऊपर, यह दो बार चलने से रोकता है। स्टीव जॉब्स की मृत्यु से पहले यह कभी नहीं हुआ !!!

सधन्यवाद Heider सती

1

आप अपने AppDelegate में इस तरह की एक पंक्ति है, तो

window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 

करें कि आप अपने plist में एक "मुख्य निब फ़ाइल आधार नाम" संपत्ति न करना पड़े "Window.xib" पर सेट है या जो भी आपकी कस्टम विंडो निब नामित है। यदि आप करते हैं, अपने विंडो instantiating के बाद की तरह

yourRootVC = [[UIViewController alloc] init]; 
[window setRootViewController:yourRootVC]; 
अपने AppDelegate में

अपने plist से उस पंक्ति को हटा दें और आप वाकई कुछ कर सकते हैं। ज्यादातर मामलों में, आप तब भी window.xib को सुरक्षित रूप से हटा सकते हैं।

1

जोड़ना [super viewDidAppear:animated]; मेरे लिए काम किया:

//Called twice 
- (void)viewDidAppear:(BOOL)animated{ 

} 

//Called once 
- (void)viewDidAppear:(BOOL)animated{ 
    [super viewDidAppear:animated]; 
} 
+1

इसे लॉग इन करने में, सुपर दो बार लोड होने से नहीं रोकता है। –

संबंधित मुद्दे