2012-04-04 3 views
9

का उपयोग कर सभी लाइव बाइट्स को मुक्त नहीं कर रहा है। मैं वर्तमान में आईओएस 5.1 में एक नेविगेशन नियंत्रक ऐप का निर्माण कर रहा हूं जो एआरसी का उपयोग करता है। मुझे अक्सर वेबपृष्ठों को प्रदर्शित करने की आवश्यकता होती है और मैंने एक वेब व्यूअर बनाया है जो कि पक्षों के चारों ओर कुछ कस्टम सामग्री के साथ एक UIWebView है। जब उपयोगकर्ता पृष्ठ को देखकर समाप्त हो जाता है तो वे बैक बटन दबाते हैं जो कस्टम वेब व्यूअर से जुड़े सभी मेमोरी को रिलीज़ करना चाहिए। मेरी समस्या यह है कि बैक बटन हिट होने पर सभी मेमोरी रिलीज़ नहीं होती हैं। मैंने एक खिलौना ऐप बनाया है (on github) कि केवल दो बटन हैं जिनमें प्रत्येक का पहला उत्तरदाता है जो एक अलग पृष्ठ पर कॉल करता है।UIWebView एआरसी

@implementation ViewController 
-(IBAction)googlePressed:(id)sender 
{ 
    CustomWebView *customWebView = [[CustomWebView alloc] initWithStringURL:@"http://www.google.com"]; 
    [self.navigationController pushViewController:customWebView animated:NO]; 
} 
-(IBAction)ksbwPressed:(id)sender 
{ 
    CustomWebView *customWebView = [[CustomWebView alloc] initWithStringURL:@"http://www.ksbw.com/news/money/Yahoo-laying-off-2-000-workers-in-latest-purge/-/1850/10207484/-/oeyufvz/-/index.html"]; 
    [self.navigationController pushViewController:customWebView animated:NO]; 
} 
-(IBAction)feedProxyPressed:(id)sender 
{ 
    CustomWebView *customWebView = [[CustomWebView alloc] initWithStringURL:@"http://feedproxy.google.com/~r/spaceheadlines/~3/kbL0jv9rbsg/15159-dallas-tornadoes-satellite-image.html"]; 
    [self.navigationController pushViewController:customWebView animated:NO]; 
} 
-(IBAction)cnnPressed:(id)sender 
{ 
    CustomWebView *customWebView = [[CustomWebView alloc] initWithStringURL:@"http://www.cnn.com/2012/04/04/us/california-shooting/index.html?eref=rss_mostpopular"]; 
    [self.navigationController pushViewController:customWebView animated:NO]; 
} 

CustomWebView सिर्फ एक UIWebView UIWebView संपत्ति को आईबी में जुड़े हुए

@implementation CustomWebView 

@synthesize webView, link; 

- (id)initWithStringURL:(NSString *) stringURL 
{ 
    if (self = [super init]) { 
     link = stringURL; 
    } 
    return self; 
} 


- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    NSURL *url = [NSURL URLWithString:link]; 
    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url]; 
    [webView loadRequest:urlRequest]; 
} 

- (void)viewDidUnload 
{ 
    [super viewDidUnload]; 
} 

मेरे समस्या मैं एक बार सब कुछ भरी हुई है प्रारंभिक ViewController होने के लिए ढेर आधारभूत सेट है कि है। मैं तो एक पृष्ठ तो लोड हो रहा है ViewController लौटने के बाद ढेर की जाँच करें और निम्नलिखित heapshots मिलती है:

Heapshots

कौन सा चलता एक बटन को दबाकर और ढेर ViewController की ओर लौटने की प्रत्येक श्रृंखला के बाद बढ़ रहा है कि भले ही कस्टमवेबव्यू सभी को रिहा किया जाना चाहिए।

संपादित करें:

नमूना परियोजना ऊपर वर्णित पाया जा सकता है on github

+0

क्या आप वाकई Zombies अक्षम हैं बनाया है पाया? – MishieMoo

+0

हां, लाश अक्षम हैं – brendan

+0

अंधेरे में शॉट लेकिन अपनी आईबीओलेट गुण (कमजोर) बनाने का प्रयास करें। – Rengers

उत्तर

0

मैं अभी तक इस्तेमाल किया एआरसी havent, लेकिन अपने कस्टम वेबव्यू कोड को देखते हुए, मुझे लगता है कि अपने WebViews आपके द्वारा बनाए गए अभी भी जीवित हैं।

यदि आप यह सुनिश्चित करना चाहते हैं कि आपके वेबव्यू ठीक से मारे गए हैं, तो सुनिश्चित करें कि दृश्य में/किया गया था, [वेबव्यू स्टॉपलोडिंग] पर कॉल करें, और वेबव्यू को नील करें।

(सावधानी: यदि आप किसी अन्य दृश्य बढ़ा रहे हैं, तो भी वेबव्यू killd किया जाएगा, ताकि उन मुद्दों में अच्छी तरह से संभाल करने के लिए सुनिश्चित कर लें) जहां भी ViewController पॉपिंग के बाद WebViews साथ

अक्सर, मैं पड़ा है मुद्दों , कुछ वेबव्यू प्रतिनिधि विधि पर वापस कॉल ऐप को क्रैश करेगा। (मुझे लगता है कि एआरसी इसे दुर्घटनाग्रस्त होने से रोकता है)।

अगर यह मदद करता है तो मुझे बताएं।

+0

कैल्विन, उत्तर के लिए धन्यवाद, लेकिन स्टॉप लोडिंग और वेबव्यू को नील करने से हेपशॉट या कुल लाइव बाइट्स नहीं बदलते हैं। इन गहन पृष्ठों के लिए, मोबाइल सफारी में बस खोलना बेहतर होगा? ऊपर दिखाए गए इस उदाहरण प्रोजेक्ट से पता चलता है कि यह साबित करना बहुत आसान है कि UIWebView सब कुछ हटा दिए जाने के बाद भी स्मृति पदचिह्न छोड़ देता है। संसाधनों की खपत के मामले में – brendan

+0

वेबव्यू महंगे हैं। मुझे यकीन नहीं है कि आपके कुल लाइव काटने क्यों नहीं बदल रहे हैं। अपने व्यू कंट्रोलर IBActions में, अपने नेविगेशन स्टैक पर व्यू कंट्रोलर को धक्का देने के बाद, क्या आप अपनी ऑब्जेक्ट्स को जारी कर रहे हैं? मैंने पहले उस विवरण को याद किया था। –

+0

आदर्श रूप से यह होना चाहिए- (IBAction) googlePressed: (id) प्रेषक { कस्टम वेब दृश्य * customWebView = [[कस्टमवेबव्यू alloc] initWithStringURL: @ "http://www.google.com"]; [self.navigationController pushViewController: customWebView एनिमेटेड: नहीं]; [कस्टम वेब दृश्य रिलीज]; } –

0

ब्रेंडन अंक की एक जोड़ी:

आप क्या हो रहा है के बारे में सुनिश्चित होने के लिए पर्याप्त कोड पोस्ट नहीं किया है। लेकिन नियंत्रक के पास एक सिंगल UIWebView क्यों नहीं है और प्रत्येक बटन प्रेस पर एक और बनाने के बजाए इसे प्रासंगिक यूआरएल के साथ बस एक स्ट्रिंग पास करें? यह एक बेहतर डिजाइन पैटर्न है जो गारंटी देगा कि आपके पास कभी भी एक से अधिक नहीं है।

+1

मैंने निर्दिष्ट तरीके से केवल एक के साथ प्रयास किया है और मुझे वही समस्याएं मिलती हैं। मैंने अपनी स्मृति समस्याओं को दिखाने के लिए जिथब पर एक नमूना प्रोजेक्ट पोस्ट किया है। https://github.com/bfruin/WebViewMemory – brendan

+0

ठीक है मैंने गिट पर अपने कोड को तुरंत देखा और कुछ भी स्पष्ट नहीं किया, लेकिन मुझे लगता है कि मुझे अंतिम विश्लेषण में कहना है: समस्या क्या है? आप एआरसी का उपयोग कर रहे हैं। मेमोरी प्रबंधन आपकी समस्या नहीं है। जब तक आप एक रिसाव नहीं देख रहे हैं, जो कि स्क्रीन शॉट में इंगित नहीं किया गया है, आपने पोस्ट किया है वास्तव में समस्या क्या है? आवंटन उपकरण का उपयोग करने का प्रयास करें और देखें कि कौन सी वस्तुएं तत्काल हैं और उनकी गणनाएं हैं। –

+0

मेरी समस्या यह है कि गिट डिस्प्ले पर पोस्ट किया गया कोड मुझे एक दृश्य नियंत्रक से लौटने पर सभी मेमोरी वापस नहीं मिलती है जिसमें वेब व्यू है। यदि ऐप सिर्फ एक वेब दर्शक था तो यह ठीक हो सकता है, लेकिन यह ऐप का एक मामूली हिस्सा है और मुझे अंततः समय के साथ कम स्मृति चेतावनियां मिलती हैं। मैं इन स्मृति मुद्दों से बचना पसंद करूंगा, लेकिन क्या एक ऐप की स्थिति को सिर्फ एक दृश्य में सहेजना ठीक होगा, अगर तक कोई रिसाव न हो तो चिंता न करें? – brendan

1

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

- (void)viewWillDisappear:(BOOL)animated 
{ 
    [super viewWillDisappear:animated]; 
    [self.webView loadHTMLString:@"<html></html>" baseURL:nil]; 
} 

यह मेरे लिए स्मृति विज्ञप्ति।

+3

मैंने इस कोड को अपनी परियोजना में जोड़ा और यह स्मृति समस्या को ठीक नहीं किया। एक नमूना प्रोजेक्ट जो मेरी समस्या को दिखाता है https://github.com/bfruin/WebViewMemory – brendan

1

UIWebView एक मेमोरी सुअर है और स्मृति को अच्छी तरह से खराब नहीं करता है। मैंने आपके कस्टमवेब व्यू क्लास में एक (शून्य) डेलोक कॉल डाला है और बैक बटन हिट होने पर इसे अपेक्षित कहा जाता है।

आप [[NSURLCache sharedURLCache] removeAllCachedResponses] कोशिश कर सकते हैं या उपयोग करना और फिर NSURLCache की अपनी स्वयं की प्रतिलिपि मुक्त है, लेकिन स्पष्ट रूप से UIWebView कभी नहीं को पूरी तरह से अपने आप के बाद साफ।

7

मैं एक ही-इश समस्या थी, मैं this little piece of magic

/* 

There are several theories and rumors about UIWebView memory leaks, and how 
to properly handle cleaning a UIWebView instance up before deallocation. This 
method implements several of those recommendations. 

#1: Various developers believe UIWebView may not properly throw away child 
objects & views without forcing the UIWebView to load empty content before 
dealloc. 

Source: http://stackoverflow.com/questions/648396/does-uiwebview-leak-memory 

*/   
[webView loadHTMLString:@"" baseURL:nil]; 

/* 

#2: Others claim that UIWebView's will leak if they are loading content 
during dealloc. 

Source: http://stackoverflow.com/questions/6124020/uiwebview-leaking 

*/ 
[webView stopLoading]; 

/* 

#3: Apple recommends setting the delegate to nil before deallocation: 
"Important: Before releasing an instance of UIWebView for which you have set 
a delegate, you must first set the UIWebView delegate property to nil before 
disposing of the UIWebView instance. This can be done, for example, in the 
dealloc method where you dispose of the UIWebView." 

Source: UIWebViewDelegate class reference  

*/ 
[webView setDelegate:nil]; 


/* 

#4: If you're creating multiple child views for any given view, and you're 
trying to deallocate an old child, that child is pointed to by the parent 
view, and won't actually deallocate until that parent view dissapears. This 
call below ensures that you are not creating many child views that will hang 
around until the parent view is deallocated. 
*/ 

[webView removeFromSuperview]; 
+0

http://www.codercowboy.com/code-uiwebview-memory-leak-prevention/ – LordParsley

+1

मैं इस ऐप को ऐप में उपयोग करता हूं जो नेविगेशन स्टैक पर कई वेब दृश्यों को धक्का देता है, लेकिन यह काम नहीं करता है।जब मैं मेमोरी चेतावनी प्राप्त करता हूं (जब दृश्य दृश्य फिर से दिखाई देता है तो उन्हें फिर से दोबारा वेब दृश्यों को साफ़ करना), जब अभिभावक दृश्य नियंत्रक का निपटारा किया जाता है, लेकिन यह काम नहीं करता है। सबसे पहले, ढेर से बाहर निकलने पर स्मृति खपत बढ़ जाती है। साथ ही, एक गहरी नेविगेशन के बाद लौटने पर, जहां मुझे यकीन है कि प्रत्येक वेब दृश्य उपरोक्त के रूप में हटा दिया गया है, ऐप अभी भी पूरी तरह से आवंटित स्मृति का अधिक उपभोग करता है। –

0

@interface WebViewViewController : UIViewController<UIWebViewDelegate>

- (void)viewDidLoad 
{ 
[super viewDidLoad]; 
NSString* urlAddress = @"http://www.google.com"; 
NSURL *url = [NSURL URLWithString:urlAddress]; 
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url]; 
self.webView.delegate = self; 
[self.webView loadRequest:requestObj]; 
} 

-(void)viewWillDisappear:(BOOL)animated{ 
[super viewWillDisappear:animated]; 
[_webView stopLoading]; 
[_webView loadHTMLString:@"<html><head></head><body></body></html>" baseURL:nil]; 
[_webView stopLoading]; 
[_webView removeFromSuperview]; 
} 

- (void)dealloc 
{ 
[_webView stopLoading]; 
} 

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error 
{ 
[_webView stopLoading]; 
_webView = nil; 
}