2012-03-26 14 views
8

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

मैं कुछ उद्देश्य-सी ऑब्जेक्ट्स को सी सरणी में स्टोर करना चाहता हूं। मैं एआरसी का उपयोग कर रहा हूँ। अगर मैं मैक पर था तो मैं इसके बजाय NSPointerArray का उपयोग करने में सक्षम हूं, लेकिन मैं आईओएस पर हूं और यह उपलब्ध नहीं है।

मैं एक त्रि-आयामी सी सरणी संग्रहित करूँगा: अवधारणात्मक रूप से मेरे आयाम दिन, ऊंचाई और कैश नम्बर हैं। प्रत्येक तत्व या तो एक उद्देश्य-सी ऑब्जेक्ट, या नल के लिए एक सूचक होगा।

कैश की संख्या (यानी कैश नम्बर आयाम का आकार) संकलन समय पर जाना जाता है, लेकिन अन्य दो ज्ञात नहीं हैं। इसके अलावा, सरणी बहुत बड़ी हो सकती है, इसलिए मुझे गतिशील रूप से इसके लिए स्मृति आवंटित करने की आवश्यकता है।

स्वामित्व अर्थशास्त्र के संबंध में, मुझे वस्तुओं के मजबूत संदर्भ की आवश्यकता है।

मैं पूरे त्रि-आयामी सरणी को एक उद्देश्य-वस्तु पर एक आवृत्ति चर होना चाहता हूं।

मैं एक विधि है कि है - tableForCacheNumber:(int)num days:(int*)days height:(int*)height के लिए योजना है। उस विधि को एक द्वि-आयामी सरणी वापस करनी चाहिए, जो एक विशिष्ट कैश संख्या है। (यह भी वापस संदर्भ द्वारा सरणी यह ​​लौटने के आकार से गुजरता है।)

मेरे सवालों का:

  • क्या आदेश मैं अपने आयाम रखना चाहिए ताकि मैं आसानी के लिए subarray के लिए सूचक लौट सकते हैं एक विशिष्ट कैश संख्या? (मुझे लगता है कि यह पहले होना चाहिए, लेकिन मैं 100% नहीं हूं।)

  • मेरी विधि का रिटर्न प्रकार क्या होना चाहिए, ताकि एआरसी शिकायत न करे? मुझे कोई फर्क नहीं पड़ता कि लौटे सरणी में संदर्भ संख्या बढ़ी है या नहीं, जब तक मुझे पता है कि यह कौन सा कर रहा है।

  • मेरे आवृत्ति चर को किस प्रकार का होना चाहिए जिसमें त्रि-आयामी सरणी होनी चाहिए? मुझे लगता है कि यह सिर्फ एक सूचक होना चाहिए, क्योंकि वह ivar सिर्फ मेरी पहली सरणी में पॉइंटर का प्रतिनिधित्व करता है जो मेरी सरणी में है। सही बात? यदि हां, तो मैं इसे कैसे निर्दिष्ट करूं?

  • जब मैं त्रि-आयामी सरणी (मेरे इवर के लिए) बनाता हूं, तो मुझे लगता है कि मैं calloc(X * Y * Z, sizeof(id)) की तरह कुछ करता हूं, और परिणाम को अपने ivar के प्रकार के रूप में डालता हूं?

  • आईवर में त्रि-आयामी सरणी से वस्तुओं तक पहुंचने पर, मेरा मानना ​​है कि मुझे प्रत्येक बार पॉइंटर को (*myArray)[4][7][2] जैसे कुछ करना होगा। सही बात?

  • दो आयामी सरणी मैं विधि से लौटने इसी तरह पहुँचा जा सकता है?

  • क्या मुझे objc_returns_inner_pointer के साथ लौटा हुआ दो-आयामी सरणी टैग करने की आवश्यकता है?

मैं एक बार फिर है कि यह एक बुरा स्टैक ओवरफ़्लो सवाल का एक सा है माफी चाहता हूँ (यह बहुत लंबा और भी कई भागों के साथ है)। मुझे आशा है कि एसओ नागरिक मुझे माफ कर देंगे। मेरे इंटरवेब कर्म को बेहतर बनाने के लिए, जब मैं इस परियोजना को भेजता हूं तो शायद मैं इसे ब्लॉग पोस्ट के रूप में लिखूंगा।

+0

[इस पृष्ठ] पर एक उदाहरण मिला (http://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-transitioningToARC/Introduction/Introduction.html) ("क्या मैं एक सी सरणी बना सकता हूं एआरसी के तहत बनाए गए पॉइंटर्स? ", नीचे के पास), जिसे मैं निकालने का प्रयास कर रहा हूं। अगर कोई उत्तर पोस्ट करना चाहता है तो भी मैं वास्तव में स्पष्टीकरण की सराहना करता हूं :) –

उत्तर

3

मेरे अपने प्रश्न का उत्तर दें क्योंकि this web page ने मुझे आवश्यक जानकारी की लापता बिट दी। मैंने ग्राहम के जवाब को भी उखाड़ फेंक दिया है, क्योंकि वह कुछ वाक्यविन्यास के चारों ओर अपने सिर को पाने में बहुत मददगार था।

जिस चाल को मैं याद कर रहा था वह जान रहा है कि अगर मैं array[1][5][2] वाक्यविन्यास के माध्यम से सरणी में आइटमों को संदर्भित करना चाहता हूं, और मुझे संकलन समय पर मेरे सरणी के आकार नहीं पता हैं, तो मैं केवल calloc() नहीं कर सकता इसके लिए डेटा का एक ब्लॉक।

सबसे आसान (हालांकि कम से कम कुशल) है कि कर की विधि को पढ़ने के लिए सिर्फ एक पाश के साथ:

__strong Item ****cacheItems; 

cacheItems = (__strong Item ****)calloc(kMaxZooms, sizeof(Item ***)); 

for (int k = 0; k < kMaxZooms; k++) 
{ 
    cacheItems[k] = (__strong Item ***)calloc((size_t)daysOnTimeline, sizeof(Item **)); 

    for (int j = 0; j < daysOnTimeline; j++) 
    { 
     cacheItems[k][j] = (__strong Item **)calloc((size_t)kMaxHeight, sizeof(Item *)); 
    } 
} 

मैं Item * रों की एक तीन आयामी सरणी का आवंटन कर रहा हूँ, Item एक उद्देश्य सी वर्ग जा रहा है। (मैं निश्चित रूप से इस स्निपेट में कोड से निपटने त्रुटि को छोड़ दिया है।)

एक बार मैं यह कर लें, मैं वर्ग कोष्ठक सिंटैक्स का उपयोग मेरी सरणी का उल्लेख कर सकते हैं:

cacheItems[zoom][day][heightToUse] = item; 

वेब पेज मैं ऊपर से जुड़ा हुआ स्मृति आवंटन करने के लिए दूसरी विधि का भी वर्णन करता है, जो प्रति आयाम calloc() पर केवल एक कॉल का उपयोग करता है। मैंने अभी तक उस विधि की कोशिश नहीं की है, जैसा कि मैंने अभी वर्णित किया है, इस समय काफी अच्छा काम कर रहा है।

0

मैं एक अलग कार्यान्वयन के बारे में सोचूंगा। जब तक यह एक demonstrable नहीं है (यानी।आपने इसे माप लिया है और इसे प्रमाणित किया है) प्रदर्शन समस्या, सादा सी सरणी में उद्देश्य-सी ऑब्जेक्ट्स को स्टोर करने का प्रयास अक्सर एक कोड गंध है।

ऐसा लगता है कि आपको एक मध्यवर्ती कंटेनर ऑब्जेक्ट की आवश्यकता है जिसे हम अब Cache पर कॉल करेंगे। प्रत्येक कैश संख्या के लिए एक उदाहरण मौजूद होगा, और आपकी ऑब्जेक्ट उनमें से एक एनएस (उत्परिवर्ती) ऐरे रखेगी। Cache ऑब्जेक्ट्स में अधिकतम दिन और ऊंचाई के लिए गुण होंगे।

कैश ऑब्जेक्ट को दो आयामों को अनुकरण करने के लिए सरल अंकगणितीय का उपयोग करके, वस्तुओं में एनएसएआरएआरई के साथ आसानी से कार्यान्वित किया जाएगा। ऑब्जेक्ट को इसके निर्देशांक द्वारा एक्सेस करने के लिए आपके कैश ऑब्जेक्ट में -objectAtDay:Height: विधि होगी।

इस तरह, स्मृति प्रबंधन के बारे में चिंता करने की कोई ज़रूरत नहीं है, एआरसी आपके लिए यह करता है।

संपादित

यह देखते हुए कि प्रदर्शन एक मुद्दा है, मैं एक 1 डी सरणी का उपयोग करें और ऑफसेट गणना करने के लिए अपने खुद के अंकगणित रोल होगा। अपने उदाहरण चर के प्रकार होगा:

__strong id* myArray; 

आप केवल सी बहुस्तरीय सबस्क्रिप्ट (array[i][j][k]) यदि आप सभी आयामों की सीमा पता उपयोग कर सकते हैं (पहले एक को छोड़कर)। इसका कारण यह है वास्तविक ऑफसेट के रूप में

(i * (max_j * max_k) + j * max_k + k) * sizeof(element type) 

गणना की जाती है संकलक max_j और max_k पता नहीं है, तो यह नहीं कर सकते। यही वह स्थिति है जिसमें आप हैं।

यह देखते हुए कि आपको 1 डी सरणी का उपयोग करना है और ऑफसेट को मैन्युअल रूप से गणना करना है, तो ऐप्पल उदाहरण आपके लिए ठीक काम करेगा।

+1

ओह, यह निश्चित रूप से एक प्रदर्शन प्रदर्शन मुद्दा है। मैंने यूआई उत्तरदायी प्राप्त करने के लिए हर फ्रेम क्या हो रहा है, प्रोफाइल करने की कोशिश कर रहे उपकरणों पर कई हफ्तों बिताए हैं। यह डिवाइस से बाहर की सभी गति को निचोड़ने के प्रयास में कोर लॉजिक का चौथा पुनर्लेख है। –

+0

आप ऑब्जेक्ट्स की सी सरणी से तेज़ी से पहुंचने के लिए आवश्यक प्राचीन संपत्ति मानों की सी सर को कैश करने के लिए बेहतर कर सकते हैं। – JeremyP

+0

@ जेरेमीपी: बहुआयामी सबस्क्रिप्ट एरे के सरणी के सरणी होने पर भरोसा करते हैं, सूचकांक के लिए अतिरिक्त अर्थ के साथ एक बड़ी एकल-आयामी सरणी नहीं। मुझे आपकी सजा नहीं है "आप केवल उपयोग कर सकते हैं ..." सही है। –

5

सबसे पहले: जब तुम NSPointerArray की जरूरत नहीं है, आप है CFMutableArrayRef कर और आप किसी भी कॉलबैक आप को बनाए रखने/रिलीज/NULL सहित विवरण, के लिए चाहते हैं पारित कर सकते हैं। यह आसान हो सकता है (और प्रदर्शन ऐसा कुछ है जिसे आप बाद में माप सकते हैं) पहले कोशिश करने के लिए।

क्रम में अपने अंक ले रहा है:

  • आप के रूप में आप उम्मीद, [cacheNumber][days][height] के रूप में अपने आयामों को परिभाषित करना चाहिए। फिर cache[cacheNumber]id *[][] प्रकार का एक द्वि-आयामी सरणी है। आप जो बोलते हैं उसे प्रदर्शन के लिए महत्वपूर्ण है के रूप में, ध्यान रखें कि इस जानवर पुनरावृत्ति करने के लिए सबसे तेज़ तरीका है:

    for (/* cacheNumber loop */) { 
    for (/* days loop */) { 
        for (/* height loop */) { 
        //... 
        } 
    } 
    } 
    
  • यह प्रकार __strong id *** में होने चाहिए: कि id के लिए सूचक के लिए सूचक के लिए सूचक है, जो है सरणी के समान ((सरणी id) के सरणी के रूप में)।

  • आपकी ivar को __strong id **** (!) होना चाहिए, क्योंकि यह उपरोक्त चीज़ों की एक सरणी है।
  • आप गलत तरीके से सरणी का आवंटन .. आप एक बहुआयामी सरणी उपयोग कर रहे हैं के बारे में लगता है कि आप इस (एक आयाम संक्षिप्तता के लिए elided) क्या करने की जरूरत:

    - (__strong id * * *)someArray { 
        __strong id * * *cache = (__strong id * * *)malloc(x*y*sizeof(void *)); 
        id hello = @"Hello"; 
    
        cache[0] = (__strong id * *)malloc(sizeof(void *)); //same for cache[1..x-1] 
        cache[0][0] = &hello; // for all cache[x][y] 
    
        return (__strong id * * *)cache; 
    } 
    
  • सही है, कि तुम कैसे उपयोग है ऐसा सूचक

  • हाँ, दो-डी सरणी उसी तरह काम करता है, संस पहला आयाम।
  • मुझे ऐसा नहीं लगता है, आप __strong ऑब्जेक्ट पॉइंटर्स सौंप रहे हैं ताकि आपको भव्य होना चाहिए। उस ने कहा, हम अब इस सामान के साथ मेरी क्षमता की सीमा के बारे में हैं इसलिए मैं गलत हो सकता था।
संबंधित मुद्दे