UIImage छवि का नामकरण: FUD


117

फ़रवरी 2014 को संपादित करें: ध्यान दें कि यह प्रश्न iOS 2.0 से आता है! तब से छवि आवश्यकताएँ और हैंडलिंग बहुत आगे बढ़ गई हैं। रेटिना छवियों को बड़ा बनाता है और उन्हें थोड़ा और अधिक जटिल लोड करता है। IPad और रेटिना छवियों के समर्थन में अंतर्निहित के साथ, आपको निश्चित रूप से अपने कोड में ImageNamed का उपयोग करना चाहिए

मैं देख रहा हूं कि बहुत से लोग कह रहे हैं imageNamedकि खराब है, लेकिन समान संख्या में लोग कहते हैं कि प्रदर्शन अच्छा है - खासकर जब रेंडरिंग UITableViewएस। उदाहरण के लिए यह SO प्रश्न देखें या iPhoneDeveloperTips.com पर यह लेख

UIImageकी imageNamedविधि लीक करने के लिए तो यह बचना ही सही था लेकिन हाल के रिलीज में तय किया गया है इस्तेमाल किया। मैं कैशिंग एल्गोरिथ्म को बेहतर ढंग से समझना चाहूंगा ताकि मैं अपनी छवियों को कैश करने के लिए सिस्टम पर भरोसा कर सकूं और जहां मुझे अतिरिक्त मील जाने की जरूरत है और खुद इसे करने की आवश्यकता है। मेरी वर्तमान बुनियादी समझ यह है कि यह फ़ाइलनाम द्वारा संदर्भित का एक सरल NSMutableDictionaryहै UIImages। यह बड़ा हो जाता है और जब मेमोरी चलती है तो यह बहुत छोटा हो जाता है।

उदाहरण के लिए, क्या कोई यह सुनिश्चित करने के लिए जानता है कि पीछे की छवि कैश का imageNamedजवाब नहीं है didReceiveMemoryWarning? ऐसा लगता नहीं है कि Apple ऐसा नहीं करेगा।

यदि आपके पास कैशिंग एल्गोरिथ्म में कोई अंतर्दृष्टि है, तो कृपया इसे यहां पोस्ट करें।


2
मैं भी। एसओ जैसा लगता है इतना जीनियस से भरा नहीं है जैसा मैंने सोचा था।
रोग

ऐसा लगता है कि आपने इसकी जांच में कुछ समय बिताया है। क्या आपने कोई ऐसा प्रयोग किया है जो नवीनतम कोकोआ-टच संस्करण के साथ UIImage छवि का कोई नकारात्मक प्रभाव दिखाएगा? एक UITableView बनाएं और कई (कई हजारों) पंक्तियों को जोड़ें और देखें कि क्या प्रदर्शन हर पंक्ति में अलग छवि दिखाने पर नीचे जाता है। शायद तब लोग आपके निष्कर्षों पर टिप्पणी कर सकते हैं।
stefanB

दरअसल, मैंने इतना प्रयोग नहीं किया है। मैं इमेजनेम का उपयोग करता हूं और हालाँकि मैं इस ऐप को मेमोरी ऑप्टिमाइज़ करना अभी बाकी हूं, मेरे पास कुछ भी नहीं है जो मैं इमेजनेम पर सीधे एक मेमोरी हॉग के रूप में इंगित कर सकता हूं। मैंने कुछ ब्लॉग पोस्टिंग की ओर इशारा किया है जो यहां imagedNamed के बारे में शिकायत कर रहे हैं और, मैंने ऐप्पल बोर्डों पर एक समान प्रश्न पूछा है जो अधिक कार्रवाई करते हैं। जब भी मेरे पास समय होगा, मैं एक सारांश और लिंक यहां दूंगा और महसूस करूंगा कि यह उन उत्तरों की घोषणा कर चुका है जो इसे प्राप्त होने जा रहे हैं।
Rog

जवाबों:


85

tldr: ImagedNamed ठीक है। यह मेमोरी को अच्छी तरह से हैंडल करता है। इसका उपयोग करें और चिंता करना बंद करें।

नवंबर 2012 को संपादित करें : ध्यान दें कि यह प्रश्न iOS 2.0 से आता है! तब से छवि आवश्यकताएँ और हैंडलिंग बहुत आगे बढ़ गई हैं। रेटिना छवियों को बड़ा बनाता है और उन्हें थोड़ा और अधिक जटिल लोड करता है। IPad और रेटिना छवियों के समर्थन में निर्मित होने के साथ, आपको निश्चित रूप से अपने कोड में ImageNamed का उपयोग करना चाहिए। अब, पोस्टर की खातिर:

बहन धागा एप्पल देव मंच पर कुछ बेहतर यातायात प्राप्त किया। विशेष रूप से Rincewind ने कुछ प्राधिकरण जोड़े।

IPhone OS 2 में ऐसे मुद्दे हैं जहाँ छवि का नाम दिया गया है: मेमोरी चेतावनी के बाद भी कैश क्लियर नहीं किया जाएगा। एक ही समय में + इमेजनाम: कैश के लिए नहीं बल्कि सुविधा के लिए बहुत अधिक उपयोग किया है, जिसने शायद समस्या को और अधिक बढ़ा दिया है।

चेतावनी देते हुए

गति के मोर्चे पर, एक सामान्य गलतफहमी है कि क्या चल रहा है। सबसे बड़ी बात यह है कि + इमेजनाम: स्रोत फ़ाइल से छवि डेटा को डीकोड करता है, जो लगभग हमेशा डेटा आकार को बढ़ाता है (उदाहरण के लिए, एक स्क्रीन आकार पीएनजी फ़ाइल संकुचित होने पर कुछ दर्जन केबी का उपभोग कर सकता है, लेकिन आधे से अधिक एमबी का उपभोग करता है विघटित - चौड़ाई * ऊंचाई * 4)। इसके विपरीत + imageWithContentsOfFile: छवि डेटा की जरूरत है कि छवि हर बार decompress होगा। जैसा कि आप कल्पना कर सकते हैं, यदि आपको केवल एक बार छवि डेटा की आवश्यकता है, तो आपने यहां कुछ भी नहीं जीता है, केवल छवि के कैश्ड संस्करण को छोड़कर चारों ओर लटके हुए हैं, और आपकी आवश्यकता से अधिक समय तक रहने की संभावना है। हालाँकि, यदि आपके पास एक बड़ी छवि है जिसे आपको अक्सर फिर से तैयार करने की आवश्यकता होती है, तो विकल्प हैं, हालांकि मैं जो मुख्य रूप से सुझाऊंगा वह बड़ी छवि को फिर से बनाने से बचने के लिए है :)।

कैश के सामान्य व्यवहार के संबंध में, यह फ़ाइल नाम के आधार पर कैश करता है (इसलिए दो उदाहरणों + छविनाम: एक ही नाम के साथ एक ही कैश्ड डेटा के संदर्भ में परिणाम होना चाहिए) और कैश गतिशील रूप से बढ़ेगा क्योंकि आप अधिक छवियों का अनुरोध करते हैं + imageNamed :. IPhone OS 2.xa बग पर मेमोरी चेतावनी मिलने पर कैश को सिकुड़ने से रोकता है।

तथा

मेरी समझ यह है कि + छवि नाम: कैश को iPhone OS 3.0 पर मेमोरी चेतावनी का सम्मान करना चाहिए। मौका मिलने पर टेस्ट करें और बग्स को रिपोर्ट करें कि क्या आपको पता है कि ऐसा नहीं है।

इसलिए यह अब आपके पास है। imageNamed: अपनी खिड़कियों को तोड़ना या अपने बच्चों की हत्या नहीं करेगा। यह बहुत आसान है, लेकिन यह एक अनुकूलन उपकरण है। अफसोस की बात है कि यह बुरी तरह से नामांकित है और कोई ऐसा समतुल्य नहीं है जिसका उपयोग करना उतना ही आसान है - इसलिए लोग इसे अधिक उपयोग करते हैं और परेशान हो जाते हैं जब यह बस अपना काम करता है

मैंने इसे ठीक करने के लिए UIImage में एक श्रेणी जोड़ी:

// header omitted
// Before you waste time editing this, please remember that a semi colon at the end of a method definition is valid and a matter of style.
+ (UIImage*)imageFromMainBundleFile:(NSString*)aFileName; {
    NSString* bundlePath = [[NSBundle mainBundle] bundlePath];
    return [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@", bundlePath,aFileName]];
}

रेनविंड ने आपके स्वयं के अनुकूलित संस्करण के निर्माण के लिए कुछ उदाहरण कोड भी शामिल किए हैं। मैं यह नहीं देख सकता कि यह मुख्य मूल्य के लायक है लेकिन यहाँ यह पूर्णता के लिए है।

CGImageRef originalImage = uiImage.CGImage;
CFDataRef imageData = CGDataProviderCopyData(
     CGImageGetDataProvider(originalImage));
CGDataProviderRef imageDataProvider = CGDataProviderCreateWithCFData(imageData);
CFRelease(imageData);
CGImageRef image = CGImageCreate(
     CGImageGetWidth(originalImage),
     CGImageGetHeight(originalImage),
     CGImageGetBitsPerComponent(originalImage),
     CGImageGetBitsPerPixel(originalImage),
     CGImageGetBytesPerRow(originalImage),
     CGImageGetColorSpace(originalImage),
     CGImageGetBitmapInfo(originalImage),
     imageDataProvider,
     CGImageGetDecode(originalImage),
     CGImageGetShouldInterpolate(originalImage),
     CGImageGetRenderingIntent(originalImage));
CGDataProviderRelease(imageDataProvider);
UIImage *decompressedImage = [UIImage imageWithCGImage:image];
CGImageRelease(image);

इस कोड के साथ व्यापार यह है कि डिकोड की गई छवि अधिक मेमोरी का उपयोग करती है लेकिन रेंडरिंग तेज है।


ऐसा लगता है कि iOS11 पर, [UIImage imageNamed:] कैश से छवियों को निकाल नहीं रहा है अगर चित्र xcasset कैटलॉग से आ रहे हैं। यह स्मृति से बाहर होने के कारण क्रैश हो जाता है।
जुराज एंटास

5

मेरे अनुभव में, ImageNamed द्वारा बनाई गई छवि कैश मेमोरी चेतावनी का जवाब नहीं देती है। मेरे पास दो एप्लिकेशन हैं जो मुझे प्रबंधन के रूप में अब तक जितने दुबले थे, लेकिन मेम की कमी के कारण अभी भी अनावश्यक रूप से दुर्घटनाग्रस्त हो रहे थे। जब मैंने छवियों को लोड करने के लिए इमेजनेम का उपयोग करना बंद कर दिया, तो दोनों अनुप्रयोग नाटकीय रूप से अधिक स्थिर हो गए।

मैं स्वीकार करता हूं कि दोनों एप्लिकेशन कुछ बड़ी छवियों को लोड करते हैं, लेकिन ऐसा कुछ भी नहीं जो पूरी तरह से सामान्य से बाहर होगा। पहले आवेदन में, मैंने बस कैशिंग को पूरी तरह से छोड़ दिया क्योंकि यह संभावना नहीं थी कि एक उपयोगकर्ता एक ही छवि में दो बार वापस आ जाएगा। दूसरे में, मैंने वास्तव में एक सरल कैशिंग क्लास का निर्माण किया, जो आपने उल्लेख किया है - एक UIImages को एक NSMutablelife में रखना और फिर मुझे मेमोरी चेतावनी मिलने पर इसकी सामग्री को फ्लश करना। यदि छवि नाम: उस तरह कैश करने के लिए थे, तो मुझे कोई प्रदर्शन उन्नयन नहीं देखना चाहिए था। यह सब 2.2 पर चल रहा था - मुझे नहीं पता कि इस पर कोई 3.0 निहितार्थ हैं।

आप इस मुद्दे के इर्द-गिर्द मेरे दूसरे सवाल को मेरे पहले ऐप से पा सकते हैं: स्टैकऑवरफ्लो सवाल UIImage कैशिंग के बारे में

एक अन्य नोट - InterfaceBuilder कवर के तहत छविनाम का उपयोग करता है। यदि आप इस समस्या में भाग लेते हैं, तो ध्यान रखें।


मैंने ठीक वैसा ही व्यवहार देखा, और फ़ाइल से पढ़ने ने सीधे इसे हल कर दिया। इसके अलावा, यह तब होता है जब मैं एक बहुत बड़ी छवि को लोड करने का प्रयास करता हूं - 11,456 x 3,226 पीएक्स, 15 एमबी। मेरा सिद्धांत है कि सिस्टम ImageNamed कैश ऑपरेशन के माध्यम से मेमोरी पार्ट-वे से बाहर निकलता है। और इस मामले के लिए कोई हैंडलिंग नहीं बनाई गई है।
डॉगवेदर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.