2011-10-17 15 views
7

यह आईओएस 4 और 5 कैमरा मैनिपुलेशन के लिए ऐप्पल द्वारा प्रदान किए गए एवीकैम नमूना कोड के आसपास जो कुछ मिला है, उसके बारे में एक सवाल और अधिक रिकॉर्ड है। मेरे लिए समस्या का लक्षण यह था कि मेरा ऐप लगभग 5-10 फ़ोटो लेने के बाद AVCamViewController लॉन्च करने पर क्रैश होगा।एवीकैम मेमोरी कम चेतावनी

मैंने मेमोरी लीक प्रोफाइलर के माध्यम से ऐप चलाया और कोई स्पष्ट रिसाव नहीं था लेकिन गतिविधि मॉनीटर के निरीक्षण के बाद मुझे पता चला कि कैमरे लॉन्च होने पर हर बार मेडिसरवर्ल्ड 17 एमबी तक बढ़ रहा था और जब यह 100 एमबी तक पहुंच गया था कई कम स्मृति चेतावनियों के साथ दुर्घटनाग्रस्त हो गया।

+0

धन्यवाद के लिए फिक्स! कृपया उत्तर को एक उत्तर में विभाजित करें, जिसे आप स्वीकार कर सकते हैं: [अपने स्वयं के प्रश्न का उत्तर देने के लिए शिष्टाचार] (http://meta.stackexchange.com/questions/17845/etiquette-for-answering-your-own-question) और [उन प्रश्नों को पोस्ट करना और उत्तर देना जिन्हें आप पहले ही जवाब दे चुके हैं] (http://meta.stackexchange.com/questions/2706/posting-and-answering-questions-you-have-already-found-the-answer-to) – sehe

+0

ने कोशिश की लेकिन क्योंकि मैं प्रीमियम उपयोगकर्ता नहीं हूं, यह मुझे 24 घंटे के भीतर अपने प्रश्न का उत्तर नहीं देगा ... इसके पास गड़बड़ करने का समय नहीं था (या जो मैं रिकॉर्ड करना चाहता था उसे भूल गया) ... मैं देखूंगा कि मैं इसे अभी कर सकता हूं या नहीं। –

उत्तर

4

एप्पल 17 Oct, 2013 नमूना कोड संशोधित, चक्र को बनाए रखने फिक्सिंग। यह समस्या init में परिभाषित ब्लॉक के भीतर self के अनुचित उपयोग के कारण है।

यहाँ संशोधन वर्णन

फिक्स्ड AVCaptureManager में चक्र है कि लीक में परिणाम को बनाए रखने के लिए है। नोट - यदि आपने अपने ऐप में AVCam कोड अनुकूलित किया है, तो आपको AVCaptureManager.m की init विधि में यहां दिए गए फ़िक्स को अपनाना चाहिए। इन सुधारों के बिना, आप AVCaptureManager उदाहरण लीक कर सकते हैं और जब आपका ऐप अग्रभूमि में होता है तो कैमरा लगातार चल रहा है।


हालांकि, ठीक वे शुरू की केवल मैनुअल के मामले में काम करता है गणना रखें। यदि आप प्रोजेक्ट पर एआरसी का उपयोग कर रहे हैं, तो release/retain कॉल और अन्य स्पष्ट चीजों से छुटकारा पाने के अलावा, weakSelf के लिए स्टोरेज क्वालीफायर __block से __weak से बदलना होगा, जैसा कि निम्नानुसार है।

__weak AVCamCaptureManager *weakSelf = self; 

वास्तव में __block का अर्थशास्त्र एआरसी के साथ बदल गया। एमआरसी में इसने चर को कमजोर संदर्भित किया, एआरसी में पहियों यह नहीं है और इस उद्देश्य के लिए __weak का उपयोग किया जाना चाहिए। इस विषय के बारे

अधिक जानकारी यहां पाया जा सकता है: How do I avoid capturing self in blocks when implementing an API?

पिछले संशोधन से नए init कार्यान्वयन का उपयोग करना और __weak बजाय __block का उपयोग कर, अंत का कारण बना dealloc विधि ठीक से कहा जाता है। https://github.com/Gabro/AVCam

विशेषताएं::

  • स्मृति मुक्त लीक
  • एआरसी का उपयोग करता


    अंत में, जो लोग पुराने विरासत कोड के आसपास ले जाने के लिए नफरत के लिए, यहाँ AVCam परियोजना का एक आधुनिक संस्करण है

  • आधुनिक उद्देश्य-सी वाक्यविन्यास
  • मामूली यूआई आईओएस 7
+0

हाय गेब्रियल, मैंने आपके AVCam प्रोजेक्ट पर एक नज़र डाली है। आप 'एआरसी संगत' टिप्पणी को 'एआरसी अनन्य' में बदल सकते हैं? मैंने इसे अपने गैर-एआरसी प्रोजेक्ट में जोड़ा है और एआरसी विशेष कार्यक्षमता के उपयोग से संबंधित कुछ संकलन विफलताओं हैं। –

+0

@RedNightingale बिल्कुल, शब्दों की भयानक पसंद वास्तव में। यदि आप चाहें तो गैर-एआरसी परियोजना में भी आप विशिष्ट फ़ाइलों पर एआरसी को चुनिंदा रूप से सक्षम कर सकते हैं। आशा करता हूँ की ये काम करेगा। –

+0

मैं उसमें देख लूंगा। ऐप्पल कोड के नए संशोधन की कोशिश की है और वे आखिरकार ठीक से काम कर रहे हैं इसलिए मैं इसे उत्तर देने के लिए प्रोत्साहित करूंगा। –

16

पहली चीज जो मैंने किया वह सभी एवीकैम फ़ाइलों के डेलोक तरीकों में लॉगिंग कर रहा था। मैंने जल्दी से पता चला कि AVCamCiewureManager और AVCamRecorder को AVCamViewController होने पर हटाया नहीं जा रहा था। मैंने बरकरार रखने और कॉल जारी करने की जांच की और वे संतुलन में दिखाई दिए, इसलिए मैंने [कैप्चर मैनेजर रिलीज] पर ब्रेकपॉइंट लगाया और पाया कि रिलीज के बाद 2 को बनाए रखा गया था (और इसलिए AVCamCaptureManager dealloc को नहीं कहा जा रहा था)।

अगला मैंने कैप्चर मैनेजर के लिए निर्माण प्रक्रिया के माध्यम से कदम उठाया और पाया कि इनिट विधि के तुरंत बाद इसे 3 की एक बार फिर से बनाए रखा गया था।

init विधि के माध्यम से कदम और जाँच हर लाइन पर गिनती बनाए रखने मैं निम्नांकित दो पंक्तियों दोनों गिनती बनाए रखने incrementing रहे थे की खोज:

[self setDeviceConnectedObserver=[notificationCenter addObserverForName:AVCaptureDeviceWasConnectedNotification object:nil queue:nil usingBlock:deviceConnectedBlock]]; 
[self setDeviceDisconnectedObserver=[notificationCenter addObserverForName:AVCaptureDeviceWasDisconnectedNotification object:nil queue:nil usingBlock:deviceDisconnectedBlock]]; 

देख रहे हैं के माध्यम से मैंने पाया कि removeObserver समकक्षों dealloc विधि अंदर थे

-(void)removeObservers { 
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 
    [notificationCenter removeObserver:[self deviceConnectedObserver]]; 
    [notificationCenter removeObserver:[self deviceConnectedObserver]]; 
} 
: मैं एक नया सार्वजनिक removeObservers विधि बनाया AVCamCaptureManager (जो नहीं कहा जा रहा था) के और इतने बनाए रखने गिनती 0.

के लिए कभी नहीं गिरा इसे ठीक करने के

और AVCamCaptureManager dealloc विधि के बाहर एक ही लाइन लेना।

कॉलिंग [captureManager removeObservers]; और फिर कॉलिंग [कब्जा प्रबंधक रिलीज]; AVCamViewController dealloc विधि में 0

गतिविधि मॉनिटर के साथ परीक्षण करने के लिए सफलतापूर्वक गिनती की संख्या को केवल 5-17 एमबी पर घुमाया गया है और क्रैशिंग स्टॉप है!

आशा है कि इससे किसी और को यह समस्या होने में मदद मिलेगी!

+1

बेहतर ... शक्तिशाली एसओ देवताओं ने मुझे अब अपने प्रश्न का उत्तर देने की इजाजत दी है;) –

+0

शक्तिशाली एसओ देवताओं ने मुझे अपना +1 देकर धन्यवाद देने की अनुमति दी है;) – sehe

+0

अच्छा विवरण। मुझे विश्वास है कि हमने इसी समस्या को मारा है। –

2

हाल ही में इस समस्या में भाग लें। मैंने पाया कि वास्तविक रूट समस्या यह थी कि डिवाइस कनेक्ट किया गया हैब्लॉक और डिवाइस डिस्कनेक्ट किए गए ब्लॉक स्पष्ट रूप से स्वयं का जिक्र कर रहे थे, जिससे चक्र बनाए रखा जाता था। इसे ठीक करने के लिए, कमजोर स्वयं का उपयोग करने के लिए उन ब्लॉकों में सभी इवर संदर्भों को बदलें।

इस तरह, आपको एक टियरडाउन विधि को स्पष्ट रूप से कॉल करने की आवश्यकता नहीं होगी।

उम्मीद है कि यह किसी और की मदद करेगा।

REF: View controller dealloc not called when using NSNotificationCenter code block method with ARC

+0

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

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