2009-04-26 8 views
31

मेरे पास एक दृश्य है जिसमें UIWebView है जो एक Google मानचित्र लोड कर रहा है (इसलिए जावास्क्रिप्ट आदि के बहुत सारे)। मेरी समस्या यह है कि यदि वेब व्यू लोडिंग समाप्त होने से पहले उपयोगकर्ता ने एनएवी बार पर 'बैक' बटन हिट किया है, तो मुझे यह स्पष्ट नहीं है कि वेब दृश्य को लोड करना बंद करने के लिए कैसे कहें और फिर इसे छोड़ दें संदेशों को हटाए गए उदाहरण में भेजा गया। मुझे यह भी यकीन नहीं है कि एक वेब व्यू इसके कंटेनर दृश्य को पूरा होने से पहले गायब हो जाता है (लेकिन अगर कोई लोड होने से पहले उपयोगकर्ता बैक बटन हिट करता है तो मुझे कोई विकल्प नहीं है)।दृश्य लोडिंग UIWebView को सुरक्षित रूप से बंद करने के तरीके को कैसे देखें?

मेरी viewWillDisappear हैंडलर में मैं इस

map.delegate=nil; 
[self.map stopLoading]; 

इस, ठीक है ज्यादातर मामलों को संभालने के लिए के रूप में प्रतिनिधि nil'ing यह मेरे विचार नियंत्रक से didFailLoadWithError भेजने के बंद हो जाता है लगता है की है। हालांकि अगर मैं अपने दृश्य की डेलोक विधि में वेब दृश्य जारी करता हूं, कभी-कभी (अंतःस्थापित) मुझे अभी भी हटाए गए उदाहरण को भेजा गया संदेश मिलेगा, जो वास्तविक पृष्ठ में चल रहे जावास्क्रिप्ट से संबंधित प्रतीत होता है, उदाहरण के लिए:

-[UIWebView webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:]: message sent to deallocated instance 0x4469ee0 

यदि मैं बस वेबदृश्य जारी नहीं करता हूं, तो मुझे ये संदेश नहीं मिलते हैं, हालांकि मुझे लगता है कि मैं वेबदृश्य को लीक कर रहा हूं।

मैं viewWillDisappear के भीतर 'stopLoading' संदेश भेजने नहीं करते हैं, और बस जारी वेबव्यू, तो मैं संदेशों इस तरह देखें:

/SourceCache/WebCore/WebCore-351.9.42/wak/WKWindow.c:250 WKWindowIsSuspendedWindow: NULL window. 

संभवतः संबंधित, मैं कभी कभी (फिर से पूरी तरह से रुक-रुक कर) एक मिल बदसूरत heisenbug जहां किसी अन्य दृश्य के navbar पर बैक बटन पर क्लिक करने से शीर्षक पॉप होगा, लेकिन दृश्य नहीं। दूसरे शब्दों में, मुझे स्टैक पर व्यू एन के शीर्षक के साथ छोड़ दिया गया है, लेकिन दृश्य दिखाना अभी भी एन + 1 देख रहा है (नतीजा यह है कि आप इस स्क्रीन पर फंस गए हैं और रूट व्यू पर वापस नहीं आ सकते हैं - आप जा सकते हैं दूसरी दिशा, यानी अधिक विचारों को धक्का दें और उस दृश्य पर वापस पॉप करें जो सही रूप से पॉप नहीं हुआ है, केवल रूट व्यू पर नहीं। ऐप छोड़ने का एकमात्र तरीका है)। दूसरी बार एक ही दृश्य पर धक्का और पॉप का एक ही अनुक्रम ठीक काम करता है।

यह विशेष मुझे नट चला रहा है। मुझे लगता है कि यह वेब दृश्य लोड होने से पहले गायब होने वाले दृश्य से संबंधित हो सकता है, यानी मुझे इस मामले में संदेह है कि यह स्मृति पर लिख सकता है और दृश्य स्टैक को भ्रमित कर सकता है। या, यह पूरी तरह से असंबंधित और कहीं और एक बग हो सकता है (मैं कभी भी डीबग बिल्ड मोड में इसे पुन: उत्पन्न करने में सक्षम नहीं हूं, यह केवल रिलीज बिल्ड सेटिंग्स के साथ होता है जब मैं इसे gdb :-) से नहीं देख सकता। मेरे डीबग रन से, मुझे नहीं लगता कि मैं कुछ भी खत्म कर रहा हूं। और मैं केवल इसे ट्रिगर करने में सक्षम हूं, अगर किसी बिंदु पर मैंने उस दृश्य को मारा है जिसमें वेब दृश्य है, और यह उसके तुरंत बाद नहीं होता है।

+3

यदि मैं आप थे, तो मैं ऐप्पल के साथ एक बग फाइल करता। वेब दृश्य को हटाए जाने के बाद किसी भी संदेश को प्राप्त नहीं किया जाना चाहिए - इसे जेएस प्रोसेसिंग और यूआरएल लोडिंग को समाप्त होने पर समाप्त करना चाहिए। मैंने कभी-कभी नौसेना आइटम समस्या देखी है, लेकिन केवल आईफोन ओएस 3.0 बीटा स्थापित करने के बाद। शायद यह एक ओएस बग भी है? –

+0

हां यही मैंने सोचा था (dealloc साफ करना चाहिए)। सेब डॉक्स आम तौर पर उनके द्वारा प्रदान की जाने वाली वस्तुओं के साथ अनुबंध पर बहुत स्पष्ट नहीं होते हैं। मैंने पहले कभी नौसेना की बात नहीं देखी है और यह मेरे कार्यक्रम में नियमित रूप से पर्याप्त होता है, मुझे लगता है कि यह कुछ ऐसा होना चाहिए जो मैं कर रहा हूं - उम्मीद है कि अगर मैं इसे ठीक करने का प्रबंधन करता हूं तो इस वेबव्यू चीज़ से संबंधित है। – frankodwyer

+0

ओह और जोड़ने के लिए, यह 2.2.1 – frankodwyer

उत्तर

52

इस पर एक बदलाव दोनों लीक और ज़ोंबी मुद्दों को ठीक करना चाहिए:

- (void)loadRequest:(NSURLRequest *)request 
{ 
    [self retain]; 
    if ([webView isLoading]) 
     [webView stopLoading]; 
    [webView loadRequest:request]; 
    [self release]; 
} 
- (void)webViewDidStartLoad:(UIWebView *)webView 
{ 
    [self retain]; 
} 
- (void)webViewDidFinishLoad:(UIWebView *)webView 
{ 
    [self release]; 
} 
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error 
{ 
    [self release]; 
} 

- (void)viewWillDisappear 
{ 
    if ([webView isLoading]) 
     [webView stopLoading]; 
} 

- (void)dealloc 
{ 
    [webView setDelegate:nil]; 
    [webView release]; 
    [super dealloc]; 
} 
+0

हाँ अच्छा जवाब, मैं इस तरह कुछ करने की सोच रहा था। आपके उत्तर में कुछ चीजें हैं जिनके बारे में मैंने नहीं सोचा था, इसलिए मैं इसे आजमाउंगा और यदि यह काम करता है तो मैं इसे स्वीकार करूंगा। दुर्भाग्य से मुझे यह कोशिश करने के लिए समय मिलने से पहले बक्षीस समाप्त हो जाएगा - लेकिन मैं जो करूँगा वह बक्षीस को फिर से खोल देगा और उस मामले में जवाब स्वीकार करेगा (केवल खुद को याद दिलाने के लिए, यह 250 बक्षीस था)। – frankodwyer

+0

मैं बक्षीस के बारे में ज्यादा चिंता नहीं करता। यह सिर्फ एक संख्या है (इसके अलावा, आधा शीर्ष जवाब पर दिया जाता है;) – rpetrich

+0

अंत में यह कोशिश करने के लिए चारों ओर मिल गया - अब तक बहुत अच्छा लग रहा है। कोई मजाकिया संदेश नहीं है और ऐसा लगता है कि हेइसेनबग ठीक हो गया है - यह बहुत ही अजीब था हालांकि मैं अभी तक खुश नहीं होगा जब तक मैंने कुछ और परीक्षण नहीं किया है। – frankodwyer

0

dealloc में एक साधारण release संदेश पर्याप्त होना चाहिए।

आपकी दूसरी समस्या समय से पहले अस्वीकृत दृश्य की तरह लगती है, लेकिन मैं कुछ कोड देखे बिना ज्यादा नहीं कह सकता।

+0

हाँ एक साधारण Dealloc में रिलीज मेरे पास है, और यह परिणाम है जो संदेश को हटाए गए उदाहरण में भेजा जा रहा है। वेबव्यू को @property (nonatomic, retain) के साथ घोषित किया गया है यदि इससे कोई फर्क पड़ता है। इसके अलावा, मेरे पास NSZombie की जांच है और अन्यथा मुझे किसी भी संदेश को हटाए गए विचारों पर नहीं जा रहा है - जैसा कि मैंने कहा है कि मैं इसे डीबग मोड में पुन: पेश नहीं कर सकता, यह केवल रिलीज़ मोड में होता है। – frankodwyer

1

इसे संभालने के कुछ तरीके हैं, लेकिन यह काम करना चाहिए। आप didFailLoadWithError संदेश चाहते हैं, यह आपको बताता है कि यह बंद हो गया है।

ध्वज सेट करना है = हाँ; वेबव्यू को स्टॉपलोडिंग भेजें।

didFailLoadWithError में :, त्रुटि के लिए जाँच जब वेबव्यू बंद हो जाता है आपको मिलता है:

अगर ((thiserror।कोड == NSURLErrorCancelled) & & (isLeaving == हाँ)) {

[otherClass performSelector: @selector (shootWebview) withObject: शून्य withDelay: 0]

}

shootWebview में WebView जारी:


विविधताओं: यदि आप, आप performSelector कर सकते हैं इसके बारे में घुड़सवार होना चाहते हैं: withObject: withDelay: [fillintheblank] की देरी के साथ, यह 10-30 सेको फोन चेक के बिना nds और आप लगभग निश्चित रूप से इसके साथ दूर हो जाएगा, हालांकि मैं इसकी सिफारिश नहीं करता।

आप किया गया हैFailLoadWithError एक ध्वज सेट करें और इसे कहीं और साफ़ करें।

या मेरे पसंदीदा, शायद आपको छोड़ने पर इसे सभी को हटाने की आवश्यकता नहीं है। क्या आप कभी उस व्यू कंटेनर को फिर से प्रदर्शित नहीं करेंगे? इसे फिर से इस्तेमाल क्यों न करें?

आपका डीबग रिलीज समस्या से अलग है, तो आप यह सुनिश्चित करने के लिए अपनी कॉन्फ़िगरेशन जांचना चाहेंगे कि यह बिल्कुल वही है। बाउंटी प्रश्न के पुनरुत्पादित हिस्से पर था, है ना? ;-)।

- ओह एक सेकंड प्रतीक्षा करें, आप वेब व्यू के साथ एक संपूर्ण व्यू कंटेनर ले जा रहे हैं। आप उपर्युक्त पर भिन्नता कर सकते हैं और पूरे कंटेनर को शूटवेब व्यू में रिलीज़ करने का इंतजार कर सकते हैं।

+0

मेरी समस्या यह है कि एक बार जब मुझे दृश्य मिल जाए तो संदेश दिखाई देगा, मेरा व्यू कंट्रोलर दूर जा रहा है और जल्द ही इसे हटा दिया जाएगा (इसके अलावा इसमें सब कुछ शामिल है, यानी वेबव्यू)। मुझे व्यू कंट्रोलर को हटाए जाने से रोकने के लिए कोई रास्ता नहीं दिख रहा है (इसे लीक किए बिना) क्योंकि यह ऐसा नहीं है जो ऐसा करता है। इसलिए किसी भी प्रतिनिधि संदेश (कभी-कभी) मेरे नियंत्रक के विघटित उदाहरण पर जा रहा है। – frankodwyer

+0

यह लिखने के बावजूद यह गड़बड़ लगता है, लेकिन मुझे लगता है कि आप अपने वेबव्यू लोडिंग कॉल और बैलेंसिनलोड और डीफफाइलोड्स में [स्वयं रिलीज] द्वारा संतुलन [स्वयं को बनाए रखने] से पहले [स्वयं को बनाए रख सकते हैं] यह सुनिश्चित करने के लिए कि वेबव्यू ठीक से पूरा होने तक सब कुछ चिपक जाए। – dieselmcfadden

+0

हाँ मैं उन पंक्तियों के साथ सोच रहा था, और आपके जैसा मैंने सोचा था कि यह थोड़ा गड़बड़ था - यह नहीं देखते कि इसे क्यों काम नहीं करना चाहिए। Rpetrich के जवाब के साथ, यह कोशिश करेंगे। – frankodwyer

1

UINavigationController बग आप अपनी पोस्ट के दूसरे भाग में वर्णन कर रहे हैं स्मृति चेतावनी के अपने को संभालने से संबंधित हो सकता है। मैंने इस घटना का अनुभव किया है और मैं स्टैक में व्यू (एन + 1) देखते समय स्मृति चेतावनी को अनुकरण करके स्टैक में इसे पुन: पेश करने में सक्षम हूं।

UIWebView एक स्मृति खाने वाला है, इसलिए हो रहा है मेमोरी चेतावनियां आश्चर्यजनक नहीं होंगी जब इसे दृश्य पदानुक्रम के हिस्से के रूप में उपयोग किया जाता है।

+0

यह दिलचस्प है, धन्यवाद। मैं स्मृति चेतावनी के जवाब में जो करना चाहता हूं उस पर पढ़ूंगा (अभी मैं इसे बिल्कुल संभाल नहीं पा रहा हूं)। मैंने वास्तव में इस मुद्दे को नहीं देखा है क्योंकि मैं 3.0 पर चले गए और मैपकिट के पक्ष में वेबव्यू को छोड़ दिया, और आम तौर पर मेमोरी हैंडलिंग के अन्य क्षेत्रों पर कड़ा हो गया। – frankodwyer

0

मुझे ओएस 3 में UIWebView का उपयोग करके इस तरह की एक ही समस्या थी - यह विवरण एक अच्छा प्रारंभिक बिंदु था, हालांकि मुझे बस नीलिंग की तुलना में मिला वेब व्यू को रिलीज़ करने से पहले वेब व्यू प्रतिनिधि को बाहर निकालें। मेरी समस्या हल हो गई है।

नमूना कोड (स्वीकार्य उत्तर - ऊपर) पढ़ना - यह बहुत अधिक ओवरकिल जैसा लगता है। जैसे [वेब दृश्य रिलीज] और वेब व्यू = नील लाइनें वही वही चीज़ जिस तरह लेखक ने चर का वर्णन किया है, घोषित किया गया है (इसलिए आपको दोनों की आवश्यकता नहीं है)। मैं सभी को बनाए रखने और रिलीज लाइनों से पूरी तरह से आश्वस्त नहीं हूं - लेकिन मुझे लगता है कि आपका लाभ अलग-अलग होगा।

0

Possibly related, I sometimes (again totally intermittent) get an ugly heisenbug where clicking the back button on some other view's navbar will pop the title, but not the view. In other words I get left with the title of view n on the stack, but the view showing is still view n+1 (the result is you're trapped on this screen and cannot get back to the root view - you can go the other direction, i.e. push more views and pop back to the view that didn't pop corrrectly, just not to the root view. The only way out is to quit the app). At other times the same sequence of pushes and pops on the same views works fine.

मैं एक memoryWarning होती है, तो इस momens में, यह एक ही समस्याओं को जन्म देती है, जब मैं कर रहा हूँ ढेर> 2 और वर्तमान दृश्य नियंत्रक सूचकांक> 2 में दृश्य नियंत्रकों के साथ प्रयोग के नेविगेशन नियंत्रक एक ही समस्या है,।

वहां 1 समाधान है, जिसे मैंने नेविगेशन कंट्रोलर में पॉप और पुश विधियों को ओवरराइड करने के साथ कई प्रयोगों के बाद पाया, दृश्य नियंत्रकों के ढेर के साथ, स्टैक किए गए व्यू कंट्रोलर आदि के लिए विचार और पर्यवेक्षण के साथ।

#import <UIKit/UIKit.h> 
#import <Foundation/Foundation.h> 

@interface FixedNavigationController : 
UINavigationController <UINavigationControllerDelegate>{ 

} 

@end 

#import "FixedNavigationController.h" 

static BOOL bugDetected = NO; 

@implementation FixedNavigationController 

- (void)viewDidLoad{ 
    [self setDelegate:self]; 
} 

- (void)didReceiveMemoryWarning{ 
    // FIX navigationController & memory warning bug 
    if([self.viewControllers count] > 2) 
     bugDetected = YES; 
} 

- (void)navigationController:(UINavigationController *)navigationController 
didShowViewController:(UIViewController *)viewController 
animated:(BOOL)animated 
{ 

    // FIX navigationController & memory warning bug 
    if(bugDetected){ 
     bugDetected = NO; 

     if(viewController == [self.viewControllers objectAtIndex:1]){ 
      [self popToRootViewControllerAnimated:NO]; 
      self.viewControllers = [self.viewControllers arrayByAddingObject:viewController]; 
     } 
    } 
} 

@end 

यह ढेर में 3 दृश्य नियंत्रकों के लिए ठीक काम करता है।

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