2012-04-30 20 views
15

NSBundle विधि pathForResource का उपयोग कर किसी छवि के पथ की खोज करना कितना आवश्यक है imageNamed का उपयोग करते समय? मैं ट्यूटोरियल कोड देखता हूं जो सीधे छवि का नाम निर्दिष्ट करता है, और तब कोड जो पहले पथ खोजने के लिए अतिरिक्त मील चला जाता है।UIImage imageNamed pathForResource की आवश्यकता है?

मेरे अनुभव में, मैंने हमेशा सीधे नाम का उपयोग किया है और यह हमेशा ठीक काम करता है। मैंने माना कि यह स्वचालित रूप से जानता था कि छवि को कैसे ढूंढें। इस से अधिक करने के लिए कितना महत्वपूर्ण या किस परिस्थिति में आवश्यक होगा?

+0

[यहां] (http://stackoverflow.com/questions/924740/dispelling-the-uiimage-imagenamed-fud) आपके कोड में नामित छवि का उपयोग करने के बारे में एक SO पोस्ट है जिसे आप पढ़ना भी चाह सकते हैं। सीधे आपके प्रश्न से संबंधित नहीं है, लेकिन मुझे यह बहुत उपयोगी पाया। – zero0cool

उत्तर

5

दस्तावेज़ कहते हैं कि "विधि एप्लिकेशन के मुख्य बंडल में निर्दिष्ट नाम के साथ एक छवि की तलाश करती है", इसलिए मैं कहूंगा कि आप हमेशा नाम का उपयोग कर सकते हैं। एकमात्र अपवाद सबफ़ोल्डर के अंदर संग्रहीत छवियां हो सकती है, खासकर जब आपके पास foo/image.png और bar/image.png है। मुझे नहीं पता कि [UIImage imageNamed:@"foo/image"] काम करेगा, लेकिन कोशिश करने के लिए यह छोटा है।

(क्या एक सा इन मामलों में भ्रामक है कि Xcode पेड़ में समूहों परिणामी एप्लिकेशन बंडल में फ़ोल्डरों के अनुरूप नहीं है। उनकी सामग्री बंडल की जड़ के लिए एक साथ तोड़ी कर रहे हैं, जब तक आप एक नीले फ़ोल्डर संदर्भ का उपयोग नियमित समूह की बजाय।)

+2

असल में आप सही हैं, यह काम करता है, लेकिन (और यह एक बड़ा है लेकिन _only_ अगर "foo" आपके बंडल में एक निर्देशिका है, इसलिए एक्सकोड में एक "नीला" फ़ोल्डर है। सबसे आम मामले में आपको "foo" की आवश्यकता नहीं है। (आदेश का बिंदु: अगर आपको केवल दस्तावेज और अनुमान लगाने का अनुमान है तो आपको जवाब नहीं देना चाहिए, अगर आपको अपनी समस्या का समाधान नहीं होता है तो आपको जवाब स्वीकार नहीं करना चाहिए - अगर आपके पास नीला फ़ोल्डर था, तो सभी अच्छे , यदि नहीं, तो यह आपके लिए काम नहीं कर सकता है।) – Rhubarb

-1

इसे आजमाएं।

[UIImage imageNamed:@"your directory path of image"] 

[UIImage imageNamed: @ "Dir1/फ़ोल्डर 1/folder2/imagename.jpeg"]

57

बिल्कुल नहीं ... मूल सवाल का जवाब है:

ImageNamed का उपयोग करते हुए UIImage बनाते समय NSBundle विधि pathForResource का उपयोग करके किसी छवि के पथ की खोज करना कितना आवश्यक है?

ज्यादा .. है कैसे सही Zoul से स्वीकार किए जाते हैं जवाब और रंगा से अन्य से एक हैं। निष्पक्ष होने के लिए: यदि आप एप्लिकेशन बंडल निर्देशिका संरचना, या (दुर्लभ) मामले के बारे में बात कर रहे हैं, तो वे सही हैं, जहां छवि एक्सकोड में "नीले" फ़ोल्डर में है (बाद में उस पर अधिक), लेकिन अधिकांश के लिए नहीं सामान्य मामलों

वैसे भी, एक सच्चे उत्तर पर।

सामान्य रूप से मुझे जवाब खोजने का प्रयास करते समय मुझे यह प्रश्न मिला। मुझे इस प्रश्न के दस्तावेज़ीकरण या अन्य उत्तरों को संतोषजनक नहीं मिला, इसलिए मैंने परीक्षण करने का फैसला किया।

मेरा परीक्षण विवरण नीचे दिया गया है, लेकिन मुझे यहां परिणामों को सारांशित करने दें। संक्षेप में, जब imageNamed का उपयोग कर: अपनी छवियों को लोड करने के लिए है, यह निर्भर करता है जहाँ आप उन्हें डाल:

  1. अगर आपकी छवियों अपनी परियोजना की जड़ में हैं, भले ही एक विशुद्ध रूप से तार्किक Xcode समूह है, तो में आयोजित नहीं , आप को पथ के बारे में सोचने की आवश्यकता नहीं है: बस छवि का नाम।

  2. अगर आपकी छवियों एक समूह है कि आपकी फ़ाइल प्रणाली में एक निर्देशिका से जुड़ा हुआ है में कर रहे हैं, के माध्यम से "जोड़ा फ़ोल्डरों के लिए समूह बना" तो आप अभी भी नाम के बारे में चिंता करने की जरूरत नहीं है।

  3. यदि आपकी छवियां "नीले" समूह में हैं, जो आपके फ़ाइल सिस्टम में "अतिरिक्त फ़ोल्डरों के लिए फ़ोल्डर संदर्भ बनाकर" निर्देशिका के माध्यम से एक निर्देशिका से जुड़ी हुई है, तो आप इसे छवि के साथ लोड कर सकते हैं नामित: एक सापेक्ष पथ निर्दिष्ट करके उपरोक्त स्वीकृत उत्तर द्वारा सुझाया गया (संयोग से?)।

  4. अगर आप imageNamed :, imageWithContentsOfFile करने के लिए मुख्य विकल्प का उपयोग :, आप वास्तव में जो आप जानना चाहते हैं कि Xcode नाविक संरचना अपने बंडल में रास्तों में तब्दील हो की जरूरत का मतलब है बंडल पथ सहित फ़ाइल, का पूर्ण पथ की आवश्यकता क्यों है निर्देशिका संरचना।

इन दो तरीकों के बीच अन्य महत्वपूर्ण मतभेद:

  • imageNamed की आवश्यकता नहीं है कि आप, जबकि imageWithContentsOfFile करता filetype विस्तार, तो केवल "आइकन" नहीं "icon.png" निर्दिष्ट पूर्ण फ़ाइल नाम की आवश्यकता होती है
  • यह पहला बिंदु दूसरी सुविधा के साथ मदद करता है: imageNamed होगा स्वचालित रूप से लोड एक छवि की रेटिना संस्करण अगर वहाँ एक है, @ 2 जोड़कर एक्स आपके फ़ाइल नाम पर। तो यदि आप रेटिना डिस्प्ले पर "आइकन" मांगते हैं तो यह "[email protected]" लोड करने का प्रयास करेगा। imageWithContentsOfFile नहीं
  • imageNamed छवि कैश करता है: और उसमें उसके चारों ओर विवाद का एक बहुत निहित है: तुम इतनी खोज या बड़े पैमाने पर वेब आप की सिफारिश आप इसे से बचना चाहिए क्योंकि यह नहीं करता है पदों की एक बहुत कुछ मिल जाएगा, तो टी अपने कैश को ठीक से साफ़ करें। हालांकि, यह साल पहले तय किया गया था, इसलिए आप को इसके कैश को साफ़ करने में विफल होने की चिंता करने की आवश्यकता नहीं है। आप अभी भी इस तथ्य के बारे में चिंता करने की ज़रूरत है कि यह कैश है, हालांकि। यदि आपकी छवियां बड़ी हैं और अक्सर लोड नहीं होती हैं, तो आप फ़ाइल से उन्हें लोड करके और उन्हें कैशिंग नहीं करके मेमोरी को सुरक्षित रखेंगे। यह लीक के साथ कुछ भी नहीं करना है: भले ही आपके पास रिसाव न हो, फिर भी आप डिवाइस पर सीमित स्मृति रखते हैं, और आप को अनावश्यक रूप से कैश नहीं करना चाहते हैं। यह क्लासिक कैशिंग ट्रेडऑफ है: आपकी स्थिति में क्या अधिक महत्वपूर्ण है? मेमोरी प्रदर्शन या सीपीयू प्रदर्शन (समय)।

तो मेरे परीक्षणों के साथ।

मैंने जो किया वह 3 सरल आइकन फ़ाइलों के साथ एक साधारण UITableView ऐप बना रहा था, जो विभिन्न तरीकों का उपयोग करके तालिका की पंक्तियों में दिखाया गया था। आइकन एक्सकोड प्रोजेक्ट संरचना में उनके स्थान में भिन्न हैं। एक्सकोड पर जोर दें। मूल प्रश्न के उत्तर को समझने की कुंजी यह है कि आईओएस ऐप में तीन पूरी तरह से अलग परियोजना निर्देशिका संरचनाएं हैं: एक्सकोड नेविगेटर में आप जो देखते हैं, वही प्रोजेक्ट के लिए फाइल सिस्टम पर एक जिसे आप खोजक में देखते हैं (एक्सकोड नेविगेटर में किसी भी आइटम पर राइट क्लिक करें और "फाइंडर में दिखाएं" चुनें) और, जिसे आप शायद ही कभी देखते हैं, तैनात ऐप की "बंडल" निर्देशिका संरचना। आप फ़ाइंडर में यह अंतिम भी देख सकते हैं - ~ ​​/ लाइब्रेरी/एप्लिकेशन सपोर्ट/आईफोन सिम्युलेटर में अपना ऐप ढूंढकर, और .app निर्देशिका में ड्रिलिंग करके। मैं आपको एक मिनट में एक तस्वीर दिखाऊंगा।

तो मेरे एप्लिकेशन में, मैं सभी तीन आइकन png छवि फ़ाइलों Xcode में अलग अलग तरीकों से घसीटा:

  1. icon1.png (एक घड़ी), मैं Xcode के मार्ग पर एक फ़ाइल के रूप में में घसीटा प्रोजेक्ट, तो मैं बाद में ने एक्सकोड में एक नया समूह बनाया और इसे में खींच लिया। इस समूह को फ़ाइल सिस्टम में किसी भी निर्देशिका द्वारा प्रदर्शित नहीं किया गया है: यह एक शुद्ध एक्सकोड समूह है। इसलिए यह नाम है: "JustGroup"

  2. icon2.png (एक आँख), मैं मूल रूप से मेरी फाइल सिस्टम "RealDir" कहा जाता निर्देशिका में डाल दिया है, और मैं Xcode में इस पूरी निर्देशिका घसीटा, और जब पूछा, मैंने चुना "किसी भी जोड़े गए फ़ोल्डर के लिए समूह बनाएं" विकल्प। इसका मतलब है कि एक्सकोड में रियलडियर समूह वास्तविक निर्देशिका से जुड़ा हुआ है जिसे फाइल सिस्टम में रीयलडियर कहा जाता है (मेरी प्रोजेक्ट निर्देशिका में) और वह icon2.png वहां है।

  3. icon3.png (एक लक्ष्य), मेरे पास एक अलग निर्देशिका में भी था, जिसे मैंने को एक्सकोड में भी खींच लिया था। केवल इस बार मैंने दूसरे रेडियो विकल्प को चुना "किसी भी जोड़े गए फ़ोल्डरों के लिए फ़ोल्डर संदर्भ बनाएं"। यह एक्सकोड में एक तथाकथित "नीला" समूह बनाता है। बाद में यह सब कुछ क्या है। मैं इस समूह (और निर्देशिका) "FolderReference" कहा जाता है

यहाँ विकल्प है कि Xcode आप देता है के एक शॉट है: Xcode navigator project structure

: Xcode's dialog when dragging a directory in

और यहाँ मेरी परियोजना संरचना Xcode पर कैसा होता है

अब, मेरे ऐप में, मैंने प्रत्येक आइकन को लोड करने के लिए दो विधियों का उपयोग किया: UIImage imageNamed: और UIImage imageWithContentsOfFile। मैंने प्रत्येक तालिका के शीर्षक के साथ अपनी तालिका में पंक्तियों का एक गुच्छा बनाया है जिसमें आइकन का नाम है: जस्ट ग्रुप, रीयलडियर या फ़ोल्डर रेफरेंस, साथ ही उपयोग की गई विधि का नाम: छवि नामित बनाम से फ़ाइल (जो मैं हूं imageWithContentsOfFile के संक्षेप के रूप में उपयोग करना)

सेल का विस्तार लेबल (शीर्षक के नीचे फेंटर टेक्स्ट) विधि को मैंने फ़ाइल या पथ नाम दिखाया है।

स्पष्ट होने के लिए, "सेफाइल" के मामले में, मैं आपके द्वारा देखे गए "रिश्तेदार" नाम पर बंडल पथ जोड़ रहा हूं। तो "fromFile" के लिए, मैं वास्तव में इस कोड का उपयोग कर रहा हूँ:

NSString *bundlePath = [[NSBundle mainBundle] bundlePath]; 
NSString *imagePath = [NSString stringWithFormat:@"%@/%@", bundlePath, filePath]; 
UIImage *image = [UIImage imageWithContentsOfFile:imagePath]; 

जहां "FilePath" पथ आप तालिका सेल विस्तार लेबल में देखते हैं। छवि के लिए नामित :, दूसरी तरफ, सेल विवरण में फ़ाइलपाथ शब्दशः पारित किया जाता है।

और पंक्ति छवि स्वाभाविक रूप से लोड की गई छवि है। इसलिए तालिका में पंक्तियों के लिए जिनके पास कोई छवि नहीं है, छवि लोडिंग विफल रही।

यहां, संक्षेप में, परिणाम हैं। यदि आप इस पोस्ट के कुछ भी नहीं पढ़ते हैं, तो कम से कम इस छवि पर एक नज़र आपको बताएगी कि आपको बस इतना ही पता होना चाहिए।

app shows which icons were loaded

यहाँ आसानी से पच अंक में बुनियादी व्याख्या दी गई है:

  • के रूप में यह imageNamed आधिकारिक दस्तावेज में कहा गया है,: विधि लोड आवेदन बंडल से छवियों। इसका मतलब है कि आपको बंडल स्थान निर्दिष्ट करने की आवश्यकता नहीं है, केवल फ़ाइल का नाम। और फिर भी, फ़ाइल का मूल नाम। दस्तावेज यहां थोड़ा पतला है, इसे वास्तव में यह स्पष्ट करना चाहिए कि यह फ़ाइल बंडल रूट निर्देशिका में दिए गए फ़ाइल पथ सापेक्ष से छवि लोड करता है।

  • (यहां किकर है, इस पर ध्यान दें) जो बंडल निर्देशिका के बारे में नियम है, आपके नियोजित ऐप के बंडल में मूल निर्देशिका को संदर्भित करता है। यदि आप अन्वेषण करते हैं, तो इसका अर्थ है ".app" निर्देशिका में। यही कारण है कि नहीं एक ही Xcode नाविक में Xcode प्रोजेक्ट, की रूट निर्देशिका के रूप में है और न ही वह पाने वाले में Xcode परियोजना के रूट निर्देशिका के रूप में ही है

  • इस वजह से, जब के लिए अपने app की तैनाती डिवाइस (या सिम्युलेटर) सभी प्रोजेक्ट निर्देशिकाओं को समूहों द्वारा जोड़ा गया फ़ोल्डर्स "के लिए प्रतिनिधित्व किया गया है flattened हैं। यही है, निर्देशिका को नजरअंदाज कर दिया गया है, और इसकी सभी सामग्री बंडल की मूल निर्देशिका में अनजाने में डंप हो गई है। (मैं "अनजाने में" कहता हूं क्योंकि यदि अलग-अलग फ़ोल्डरों में एक ही नाम वाली फाइलें हैं, तो वे यहां टकराएंगे और आपको समस्याओं का समाधान करने में कोई मदद नहीं मिलेगी।) यह मेरे उदाहरण में रियलडियर का मामला है: में तैनात ऐप, RealDir अब मौजूद नहीं है, और icon2.png सामान्य जनसंख्या (डरावनी) के साथ मिश्रण करने के लिए छोड़ दिया गया है। यह लगभग बिना कहने के चला जाता है कि "जस्ट ग्रुप", पूरी तरह तार्किक एक्सकोड समूह को भी अनदेखा किया जाता है - यह कभी भी असली निर्देशिका नहीं था, वैसे भी एक्सकोड उपयोगकर्ता के लिए एक दृश्य सहायता - और icon1.png भी बंडल रूट में है।

    • यही कारण है कि imageNamed: icon2 लोड करने में सक्षम था।

    • और यह भी कारण है कि imageWithContentsOfFile "RealDir/image2.png" में यह पता लगाने के लिए सक्षम नहीं था: क्योंकि वहाँ तैनात एप्लिकेशन में कोई RealDir निर्देशिका है।

  • "नीले फ़ोल्डर", दूसरे हाथ पर, वह है, निर्देशिका द्वारा "जोड़ा फ़ोल्डरों के लिए फ़ोल्डर संदर्भ", एप्लिकेशन बंडल निर्देशिका संरचना में बनाए रखा वास्तव में प्रतिनिधित्व किया। यह स्पष्ट रूप से नीले फ़ोल्डर्स का बिंदु है: वे आपको आपके तैनात ऐप में निर्देशिका संरचना बनाने का एक तरीका देते हैं। मुझे इसके लिए मूल राइस डी'एट्रे का यकीन नहीं है, लेकिन एक अच्छा उपयोग केस है जहां आपके पास एक ही नाम के साथ संसाधन फ़ाइलों के वैकल्पिक संस्करणों वाली कई निर्देशिकाएं हैं और आप चाहते हैं कि आपका ऐप रनटाइम पर उनके बीच स्विच करने में सक्षम हो निर्देशिका बदलकर। वैसे भी, मेरे फ़ोल्डर संदर्भ में icon3.png, तैनात ऐप में मेरी फ़ोल्डर रिफरेंस निर्देशिका में बना रहा।

    • यही कारण है कि imageNamed है: यह "icon3" के साथ नहीं मिल सकता है, लेकिन के साथ "FolderReference/icon3" यह मिल सकता है
    • imageWithContentsOfFile यह भी FolderReference का उपयोग कर खोजने के लिए सक्षम था, लेकिन केवल जब संलग्न हो, ऊपर दिए गए कोड का उपयोग कर पूर्ण बंडल पथ को याद रखें। (यहां मुख्य अंतर: छवि नामित इस मामले में एक सापेक्ष पथ के साथ काम करता है, imageWithContentsOfFile हमेशा एक पूर्ण पथ के साथ काम करता है)।

स्पष्ट करने के लिए, यहाँ मेरी फ़ोल्डर संरचनाएँ हैं: अंत में, Finder Xcode project directory structure

और शायद:

तुम मेरे Xcode प्रोजेक्ट नाविक संरचना ऊपर देखा, यहां फाइल सिस्टम निर्देशिका इसे नीचे है सबसे महत्वपूर्ण बात यह है कि तैनात बंडल फ़ाइल सिस्टम निर्देशिका संरचना: deployed bundle directory structure

नोट: मुझे टी नहीं मिला मेरे मैक पर इस स्थान पर: आपको अपना एक ही स्थान पर मिल जाएगा - आपको यह पता लगाने के लिए थोड़ा सा खोजना पड़ सकता है कि कौन सी बदसूरत-GUID- नामित उपनिर्देशिका में आपका ऐप शामिल है।

~/Library/Application Support/iPhone Simulator/5.1/Applications/4EB386B2-CD7E-4590-9757-18DDDEE6AF4F/ImageLoadingTest.app 

मुझे उम्मीद है कि इससे मदद मिलती है। परीक्षण, अन्वेषण और अंत में, का वर्णन करने से यह निश्चित रूप से मेरी मदद करता है।

+0

से नीचे दिए गए विषय पर लंबे हवादार ग्रंथ देखें, यह उत्तर देना चाहिए, धन्यवाद पोस्ट करने के लिए वैसे भी। – dashesy

+0

यह एक बहुत ही उपयोगी उत्तर है, और मेरे लिए इस मुद्दे को मंजूरी दे दी है। स्वीकार्य उत्तर होना चाहिए था। ऊपर और धन्यवाद। – scottburton11

+1

यह स्वीकार्य उत्तर क्यों नहीं था? यह शानदार है! –

0

मैंने एक नया एक्सकोड प्रोजेक्ट बनाया (एकल दृश्य, ऐपडेलेगेट, व्यू कंट्रोलर क्लास, स्टोरीबोर्ड इत्यादि)। एक छवि समूह बनाया गया। 16x16 पीएनजी फ़ाइल Wall1.png बनाने के लिए प्रयुक्त पेंटब्रश और इसे एक्सकोड में छवि समूह में गिरा दिया (एक्सकोड फाइलों की प्रतिलिपि बनाने दें)।

ViewController viewDidLoad विधि में कोड कहा:

UIImageView* imageView=[[UIImageView alloc] initWithFrame:CGRectMake(50, 100, 16, 16)]; 
UIImage *image = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:@"Images/Wall1" ofType:@"png"]]; 
imageView.image = image; 
    UIImageView* imageView=[[UIImageView alloc] initWithFrame:CGRectMake(50, 100, 16, 16)]; 
UIImage *image = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:@"Wall1" ofType:@"png"]]; 
imageView.image = image; 
[self.view addSubview:imageView]; 

मेरे फोन पर एप्लिकेशन Ran, छवि

प्रदर्शित नहीं होगा जोड़ा गया [self.view addSubview: imageView] में एक को तोड़ने बिंदु;

छवि अशक्त

खोला टर्मिनल और अपने प्रोजेक्ट के लिए बदली हुई निर्देशिका, Wall1.png नहीं था एक समूह फ़ोल्डर छवियाँ था। प्रोजेक्ट से पीएनजी को हटा दिया, एक छवि फ़ोल्डर बनाया, फ़ोल्डर में Wall1.png ले जाया गया। समूह छवियों में मौजूदा फ़ाइल Wall1.png जोड़ा गया।

ऐप को चलाएं, छवि अभी भी दिखाई नहीं दे रही है। आप अपने चित्रों के लिए एक समूह बनाते हैं

छवि अशक्त

बदली गई छवियाँ/Wall1 Wall1

करने के लिए एप्लिकेशन Ran था, बूम छवि displayed1

है, Xcode एक संबंधित निर्देशिका का निर्माण नहीं करता। यदि आप चाहते हैं तो मैन्युअल रूप से बनाएं (मैं अपनी छवियों को एक अलग फ़ोल्डर में रखना पसंद करता हूं)। UIImage imageWithContentsOfFile का उपयोग करते समय अपनी छवि फ़ाइल का पूरा पथ निर्दिष्ट न करें।