NSArray में सी-स्ट्रक्चर लगाने का सबसे अच्छा तरीका क्या है?


89

एक में सी-संरचनाओं को स्टोर करने का सामान्य तरीका क्या है NSArray? फायदे, नुकसान, मेमोरी हैंडलिंग?

विशेष रूप से, क्या अंतर है valueWithBytesऔर valueWithPointer - जस्टिन और कैटफ़िश द्वारा नीचे उठाया गया है।

यहांvalueWithBytes:objCType: जानिए भविष्य के पाठकों के लिए Apple की चर्चा की एक कड़ी ...

कुछ पार्श्व सोच और प्रदर्शन में अधिक देखने के लिए, एवेरियन ने C ++STL::vector में उपयोग करने का मुद्दा उठाया है ।

(यह एक दिलचस्प मुद्दा उठाता है: क्या एक तेज सी लाइब्रेरी है, STL::vectorलेकिन इसके विपरीत बहुत हल्का नहीं है, जो न्यूनतम "व्यवस्थित सरणियों के सुव्यवस्थित संचालन" की अनुमति देता है ...? "

तो मूल प्रश्न ...

उदाहरण के लिए:

typedef struct _Megapoint {
    float   w,x,y,z;
} Megapoint;

तो: क्या सामान्य, सबसे अच्छा, मुहावरेदार तरीका है कि एक में अपनी खुद की संरचना को स्टोर करने के लिए NSArrayऔर कैसे आप उस मुहावरे में स्मृति को संभालते हैं?

कृपया ध्यान दें कि मैं विशेष रूप से सामान्य मुहावरों की तलाश कर रहा हूं, जो संरचना को संग्रहीत करते हैं। बेशक, कोई नई छोटी कक्षा बनाकर इस मुद्दे से बच सकता है। हालाँकि मैं जानना चाहता हूँ कि वास्तव में किसी सरणी में स्ट्रक्चर्स लगाने के लिए सामान्य मुहावरा कैसा है, धन्यवाद।

BTW यहाँ NSData दृष्टिकोण जो शायद है? सबसे अच्छा नहीं ...

Megapoint p;
NSArray *a = [NSArray arrayWithObjects:
    [NSData dataWithBytes:&p length:sizeof(Megapoint)],
    [NSData dataWithBytes:&p length:sizeof(Megapoint)],
    [NSData dataWithBytes:&p length:sizeof(Megapoint)],
        nil];

BTW संदर्भ के रूप में और Jarret हार्डी के लिए धन्यवाद, यहाँ कैसे स्टोर करने के लिए CGPointsऔर एक में समान है NSArray:

NSArray *points = [NSArray arrayWithObjects:
        [NSValue valueWithCGPoint:CGPointMake(6.9, 6.9)],
        [NSValue valueWithCGPoint:CGPointMake(6.9, 6.9)],
        nil];

(देखें कि कैसे मैं एक आसान तरीके से NSArray में CGPoint ऑब्जेक्ट्स जोड़ सकता हूँ? )


NSData में इसे परिवर्तित करने के लिए आपका कोड ठीक होना चाहिए .. और बिना किसी मेमोरी लीक के .... हालांकि, एक व्यक्ति मानक सी ++ सरणी का उपयोग कर सकता है मेगापॉइंट पी [3];
स्वप्निल लुक्टुक

जब तक प्रश्न दो दिन पुराना नहीं हो जाता, तब तक आप एक इनाम नहीं जोड़ सकते।
मैथ्यू फ्रेडरिक

1
यद्यपि OSX के लिए valueWithCGPoint उपलब्ध नहीं है। यह UIKit का हिस्सा है
lppier

@Ippier valueWithPoint OS X
Schpaencoder

जवाबों:


159

NSValue केवल CoreGraphics संरचनाओं का समर्थन नहीं करता है - आप इसे अपने लिए भी उपयोग कर सकते हैं। मैं ऐसा करने की सलाह दूंगा, क्योंकि NSDataसाधारण डेटा संरचनाओं की तुलना में कक्षा शायद हल्का वजन है ।

बस निम्नलिखित की तरह एक अभिव्यक्ति का उपयोग करें:

[NSValue valueWithBytes:&p objCType:@encode(Megapoint)];

और मान वापस पाने के लिए:

Megapoint p;
[value getValue:&p];

4
@ जॉय ब्लो @ कैटफ़िश_मैन यह वास्तव में संरचना को कॉपी करता है p, न कि इसे पॉइंटर को। @encodeनिर्देश सभी जानकारी कितना बड़ा संरचना है के बारे में आवश्यक प्रदान करता है। जब आप NSValue(या जब सरणी करता है) रिलीज़ करते हैं , तो इसकी संरचना की प्रतिलिपि नष्ट हो जाती है। यदि आपने getValue:इस बीच उपयोग किया है, तो आप ठीक हैं। "नंबर और वैल्यू प्रोग्रामिंग टॉपिक्स" के "वैल्यूज़िंग वैल्यूज़" सेक्शन को देखें: developer.apple.com/library/ios/documentation/Cocoa/Conceptual/…
जस्टिन स्पाहर-सममर

1
@ जॉय ब्लो ज्यादातर सही है, सिवाय इसके कि यह रनटाइम में बदलने में सक्षम नहीं होगा । आप एक सी प्रकार निर्दिष्ट कर रहे हैं, जिसे हमेशा पूरी तरह से जाना जाना चाहिए। यदि यह अधिक डेटा संदर्भित करके "बड़ा" प्राप्त कर सकता है, तो आप संभवतः एक पॉइंटर के साथ इसे लागू करेंगे, और @encodeउस पॉइंटर के साथ संरचना का वर्णन करेंगे, लेकिन पूरी तरह से इंगित किए गए डेटा का वर्णन नहीं करेंगे , जो वास्तव में बदल सकता है।
जस्टिन स्पाहर-समर्स

1
निपटाए जाने पर NSValueस्वचालित रूप से संरचना की मेमोरी को मुक्त कर देगा ? इस पर प्रलेखन थोड़ा अस्पष्ट है।
devios1

1
तो बस पूरी तरह से स्पष्ट होने के लिए, उस NSValueडेटा का स्वामी है जो खुद को कॉपी करता है और मुझे इसे (एआरसी के तहत) मुक्त करने के बारे में चिंता करने की ज़रूरत नहीं है?
devios1

1
@devios सही है। NSValueवास्तव में कोई "मेमोरी मैनेजमेंट" नहीं करता है, प्रति से-आप इसे केवल आंतरिक रूप से संरचना मूल्य की एक प्रति होने के रूप में सोच सकते हैं। उदाहरण के लिए, यदि संरचना में नेस्टेड पॉइंटर्स होते हैं, NSValueतो उन लोगों के साथ मुक्त या कॉपी करना या कुछ भी करना नहीं जानते हैं - यह उन्हें अछूता छोड़ देगा, पते को कॉपी करना-जैसा है।
जस्टिन स्पाहर-समर्स

7

मेरा सुझाव है कि आप NSValueमार्ग से चिपके रहेंगे , लेकिन अगर आप वास्तव structमें अपने NSArray (और कोको में अन्य संग्रह वस्तुओं) में सादे 'ol datatypes को स्टोर करने की इच्छा रखते हैं , तो आप ऐसा कर सकते हैं - यद्यपि मुख्य रूप से कोर फाउंडेशन और टोल-फ्री ब्रिजिंग का उपयोग करते हुए ।

CFArrayRef(और उसके परस्पर समकक्ष CFMutableArrayRef) , एक सरणी ऑब्जेक्ट बनाते समय डेवलपर को अधिक लचीलापन देता है। नामित प्रारंभिक के चौथे तर्क को देखें:

CFArrayRef CFArrayCreate (
    CFAllocatorRef allocator,
    const void **values,
    CFIndex numValues,
    const CFArrayCallBacks *callBacks
);

यह आपको यह अनुरोध करने की अनुमति देता है कि CFArrayRefऑब्जेक्ट कोर फाउंडेशन की स्मृति प्रबंधन दिनचर्या का उपयोग करता है, कोई भी या यहां तक ​​कि आपकी खुद की स्मृति प्रबंधन दिनचर्या।

अप्रचलित उदाहरण:

// One would pass &kCFTypeArrayCallBacks (in lieu of NULL) if using CF types.
CFMutableArrayRef arrayRef = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
NSMutableArray *array = (NSMutableArray *)arrayRef;

struct {int member;} myStruct = {.member = 42};
// Casting to "id" to avoid compiler warning
[array addObject:(id)&myStruct];

// Hurray!
struct {int member;} *mySameStruct = [array objectAtIndex:0];

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

मैं इस समाधान की सिफारिश नहीं करूंगा, लेकिन इसे किसी अन्य व्यक्ति के हित में होने पर यहां रखूंगा। :-)


हीप पर आबंटित (स्टैक के बदले में) के रूप में अपनी संरचना का उपयोग करके यहां प्रदर्शित किया गया है:

typedef struct {
    float w, x, y, z;
} Megapoint;

// One would pass &kCFTypeArrayCallBacks (in lieu of NULL) if using CF types.
CFMutableArrayRef arrayRef = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
NSMutableArray *array = (NSMutableArray *)arrayRef;

Megapoint *myPoint = malloc(sizeof(Megapoint);
myPoint->w = 42.0f;
// set ivars as desired..

// Casting to "id" to avoid compiler warning
[array addObject:(id)myPoint];

// Hurray!
Megapoint *mySamePoint = [array objectAtIndex:0];

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

@ जो ब्लो: यह एक उत्कृष्ट बिंदु है जिसे आप मेमोरी प्रबंधन के बारे में बनाते हैं। आप भ्रमित होने के लिए सही हैं: मैंने जो कोड नमूना ऊपर पोस्ट किया है वह रहस्यमय दुर्घटनाओं का कारण बनेगा, यह इस बात पर निर्भर करता है कि फ़ंक्शन का स्टैक कब ओवरराइट किया गया है। मैं इस बारे में विस्तार से बताने लगा कि मेरे समाधान का उपयोग कैसे किया जा सकता है, लेकिन मैंने महसूस किया कि मैं ऑब्जेक्टिव-सी की अपनी संदर्भ-गणना को फिर से लागू कर रहा हूं। कॉम्पैक्ट कोड के लिए मेरी माफी - यह योग्यता की नहीं बल्कि आलस्य की बात है। कोड लिखने का कोई मतलब नहीं है जो अन्य नहीं पढ़ सकते हैं। :)
सेडियन एलियन

यदि आप "लीक" (बेहतर शब्द के लिए) के लिए खुश थे struct, तो आप निश्चित रूप से इसे एक बार आवंटित कर सकते हैं और भविष्य में इसे मुफ्त नहीं कर सकते। मैंने अपने संपादित उत्तर में इसका एक उदाहरण शामिल किया है। इसके अलावा, यह टाइपो के लिए नहीं था myStruct, क्योंकि यह ढेर पर आवंटित एक संरचना थी, जो एक सूचक से ढेर पर आवंटित एक संरचना से अलग थी।
सेडेन एलियन

4

सी संरचना को जोड़ने के लिए एक समान विधि पॉइंटर को स्टोर करने और पॉइंटर को डी-रेफर करने के लिए है;

typedef struct BSTNode
{
    int data;
    struct BSTNode *leftNode;
    struct BSTNode *rightNode;
}BSTNode;

BSTNode *rootNode;

//declaring a NSMutableArray
@property(nonatomic)NSMutableArray *queues;

//storing the pointer in the array
[self.queues addObject:[NSValue value:&rootNode withObjCType:@encode(BSTNode*)]];

//getting the value
BSTNode *frontNode =[[self.queues objectAtIndex:0] pointerValue];

3

यदि आप निरर्थक महसूस कर रहे हैं, या वास्तव में बनाने के लिए बहुत सारी कक्षाएं हैं: यह कभी-कभी उपयोगी रूप से एक objc वर्ग (रेफरी class_addIvar) का निर्माण करने के लिए उपयोगी है । इस तरह, आप मनमाने ढंग से objc कक्षाएं बना सकते हैं। आप फ़ील्ड द्वारा फ़ील्ड निर्दिष्ट कर सकते हैं, या बस संरचना की जानकारी पास कर सकते हैं (लेकिन यह व्यावहारिक रूप से NSData की प्रतिकृति है)। कभी-कभी उपयोगी, लेकिन अधिकांश पाठकों के लिए शायद यह एक 'मज़ेदार तथ्य' है।

मैं इसे यहां कैसे लागू करूंगा?

आप class_addIvar को कॉल कर सकते हैं और एक नए वर्ग में मेगापॉइंट उदाहरण चर जोड़ सकते हैं, या आप रनटाइम पर मेगापॉइंट क्लास के एक ओब्जेक्ट वेरिएंट को संश्लेषित कर सकते हैं (उदाहरण के लिए, मेगापॉइंट के प्रत्येक क्षेत्र के लिए एक उदाहरण चर)।

पूर्व संकलित objc वर्ग के बराबर है:

@interface MONMegapoint { Megapoint megapoint; } @end

उत्तरार्द्ध संकलित objc वर्ग के बराबर है:

@interface MONMegapoint { float w,x,y,z; } @end

आपके द्वारा ivars जोड़ने के बाद, आप विधियों को जोड़ / संश्लेषित कर सकते हैं।

प्राप्त अंत पर संग्रहीत मूल्यों को पढ़ने के लिए, अपने संश्लेषित तरीकों का उपयोग करें object_getInstanceVariable, याvalueForKey: (जो अक्सर इन स्केलर उदाहरण चर को NSNumber या NSValue अभ्यावेदन में बदल देगा)।

btw: आपके द्वारा प्राप्त सभी उत्तर उपयोगी हैं, कुछ संदर्भ / परिदृश्य के आधार पर बेहतर / बदतर / अमान्य हैं। मेमोरी, गति, बनाए रखने में आसानी, हस्तांतरण या संग्रह करने में आसानी आदि के बारे में विशिष्ट आवश्यकताएं निर्धारित करेंगी जो किसी दिए गए मामले के लिए सबसे अच्छा है ... लेकिन कोई 'सही' समाधान नहीं है जो हर संबंध में आदर्श हो। NSArray में सी-स्ट्रक्चर लगाने का कोई सबसे अच्छा तरीका नहीं है, बस एक 'सबसे अच्छा तरीका है NSArray में एक विशिष्ट परिदृश्य, केस, या आवश्यकताओं के सेट के लिए सी-स्ट्रक्चर डालना ' - जो आपके पास होगा विस्तृत विवरण देना।

इसके अलावा, NSArray सूचक आकार (या छोटे) प्रकारों के लिए आमतौर पर पुन: प्रयोज्य सरणी इंटरफ़ेस है, लेकिन ऐसे अन्य कंटेनर हैं जो कई कारणों से सी-स्ट्रक्चर के लिए बेहतर अनुकूल हैं (एसटी :: वेक्टर सी-स्ट्रक्चर के लिए एक विशिष्ट पसंद है)।


लोगों की पृष्ठभूमि के रूप में अच्छी तरह से खेलने में आते हैं ... कैसे आप का उपयोग करने की जरूरत है कि संरचना अक्सर कुछ संभावनाओं को खत्म करेगा। 4 फ़्लोट्स बहुत मूर्खतापूर्ण है, लेकिन एक सन्निहित स्मृति प्रतिनिधित्व (जैसे, NSData) का उपयोग करने के लिए संरचनात्मक लेआउट / आर्किटेक्चर बहुत भिन्न होते हैं और काम करने की अपेक्षा करते हैं। गरीब आदमी के ओब्जेक्ट सीरियलाइज़र की संभावना सबसे धीमी निष्पादन समय होती है, लेकिन यह सबसे संगत है यदि आपको किसी भी ओएस एक्स या आईओएस डिवाइस पर मेगापॉइंट को बचाने / खोलने / प्रसारित करने की आवश्यकता है। सबसे आम तरीका है, मेरे अनुभव में बस एक objc वर्ग में संरचना को रखना है। अगर आप इस सब के बीच से गुजर रहे हैं (कॉन्टेस्ट)
justin

(cont) यदि आप नए संग्रह प्रकार सीखने से बचने के लिए केवल इस परेशानी से गुज़र रहे हैं - तो आपको नया संग्रह प्रकार सीखना चाहिए =) std::vector(उदाहरण के लिए) C / C ++ प्रकार, स्ट्रक्चर्स और कक्षाओं को धारण करने के लिए अधिक अनुकूल है NSArray। NSValue, NSData, या NS सहकर्मी प्रकार के NSArray का उपयोग करके, आप एक टन आवंटन और रनटाइम ओवरहेड जोड़ते समय बहुत प्रकार की सुरक्षा खो रहे हैं। यदि आप सी के साथ रहना चाहते हैं, तो वे आमतौर पर स्टैक पर मॉलोक और / या सरणियों का उपयोग करेंगे ... लेकिन आपके साथ std::vectorअधिकांश जटिलताओं को छुपाता है।
जस्टिन डेस

वास्तव में, यदि आप सरणी हेरफेर / पुनरावृत्ति चाहते हैं जैसा कि आपने उल्लेख किया है - stl (c ++ मानक पुस्तकालयों का हिस्सा) इसके लिए बहुत अच्छा है। आपके पास चुनने के लिए और अधिक प्रकार हैं (जैसे, यदि पहुंच / निकालें पढ़ने के एक्सेस समय से अधिक महत्वपूर्ण है), और कंटेनरों में हेरफेर करने के लिए मौजूदा तरीकों के टन। यह भी - यह c ++ में नंगी मेमोरी नहीं है - कंटेनर और टेम्प्लेट फ़ंक्शंस टाइप-जागरूक हैं, और संकलन पर जाँच की गई - NSData / NSValue अभ्यावेदन से एक मनमाना बाइट स्ट्रिंग खींचने की तुलना में अधिक सुरक्षित है। उनके पास सीमा की जाँच और स्मृति के ज्यादातर स्वचालित प्रबंधन भी हैं। (प्रतियोगिता)
जस्टिन

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

यह आपके निपटान में सिर्फ एक और उपकरण है। c ++, c ++ के साथ objc, c के साथ c ++ या कई अन्य संयोजनों के साथ objc को एकीकृत करने में जटिलताएं हो सकती हैं। भाषा सुविधाओं को जोड़ना और कई भाषाओं का उपयोग करना किसी भी मामले में कम लागत पर आता है। यह सभी तरह से चला जाता है। उदाहरण के लिए, बिल्ड समय तब बढ़ता है जब objc ++ के रूप में संकलित किया जाता है। साथ ही, इन स्रोतों का अन्य परियोजनाओं में आसानी से उपयोग नहीं किया जाता है। यकीन है, आप भाषा सुविधाओं को फिर से लागू कर सकते हैं ... लेकिन यह अक्सर सबसे अच्छा समाधान नहीं है। एक objc परियोजना में c ++ को एकीकृत करना ठीक है, यह एक ही परियोजना में objc और c स्रोतों का उपयोग करने के रूप में 'गन्दा' है। (cont
justin

3

यदि आप इस डेटा को कई ऐबिस / आर्किटेक्चर में साझा कर रहे हैं, तो गरीब-आदमी के objc क्रमांक का उपयोग करना सबसे अच्छा होगा:

Megapoint mpt = /* ... */;
NSMutableDictionary * d = [NSMutableDictionary new];
assert(d);

/* optional, for your runtime/deserialization sanity-checks */
[d setValue:@"Megapoint" forKey:@"Type-Identifier"];

[d setValue:[NSNumber numberWithFloat:mpt.w] forKey:@"w"];
[d setValue:[NSNumber numberWithFloat:mpt.x] forKey:@"x"];
[d setValue:[NSNumber numberWithFloat:mpt.y] forKey:@"y"];
[d setValue:[NSNumber numberWithFloat:mpt.z] forKey:@"z"];

NSArray *a = [NSArray arrayWithObject:d];
[d release], d = 0;
/* ... */

... खासकर अगर संरचना समय के साथ बदल सकती है (या लक्षित मंच से)। यह अन्य विकल्पों की तरह तेज़ नहीं है, लेकिन इसकी कुछ परिस्थितियों में टूटने की संभावना कम है (जो आपने महत्वपूर्ण के रूप में निर्दिष्ट नहीं किया है या नहीं)।

यदि अनुक्रमित प्रतिनिधित्व प्रक्रिया से बाहर नहीं निकलता है, तो मनमाने ढंग से संरचनाओं के आकार / क्रम / संरेखण को नहीं बदलना चाहिए, और ऐसे विकल्प हैं जो सरल और तेज हैं।

या तो घटना में, आप पहले से ही एक रेफ़-काउंटेड ऑब्जेक्ट (NSData, NSValue की तुलना में) जोड़ रहे हैं ... ताकि एक objc क्लास बनाई जाए जो मेगापॉइंट रखती है और कई मामलों में सही उत्तर है।


@ जो कुछ है जो धारावाहिक प्रदर्शन करता है। संदर्भ के लिए: en.wikipedia.org/wiki/Serialization , parashift.com/c++-faq-lite/serialization.html , साथ ही साथ Apple के "अभिलेखागार और सीरियल प्रोग्रामिंग गाइड"।
जस्टिन

xml फ़ाइल को ठीक से ग्रहण करना कुछ का प्रतिनिधित्व करता है, तो हाँ - यह मानव-पढ़ने योग्य क्रमांकन का एक सामान्य रूप है।
जस्टिन

0

मेरा सुझाव है कि आप std :: वेक्टर या std :: C / C ++ प्रकारों की सूची का उपयोग करें, क्योंकि पहली बार में यह NSArray की तुलना में अधिक तेज़ है, और दूसरा अगर आपके लिए पर्याप्त गति नहीं होगी - तो आप हमेशा अपना स्वयं का बना सकते हैं एसटीएल कंटेनरों के लिए एलोकेटर और उन्हें और भी तेज बना सकते हैं। सभी आधुनिक मोबाइल गेम, भौतिकी और ऑडियो इंजन आंतरिक डेटा को स्टोर करने के लिए STL कंटेनरों का उपयोग करते हैं। सिर्फ इसलिए कि वे वास्तव में उपवास करते हैं।

यदि यह आपके लिए नहीं है - NSValue के बारे में लोगों के अच्छे उत्तर हैं - मुझे लगता है कि यह सबसे स्वीकार्य है।


STL आंशिक रूप से C ++ मानक पुस्तकालय में शामिल एक पुस्तकालय है। en.wikipedia.org/wiki/Standard_Template_Library cplusplus.com/reference/stl/vector
इवेंज बोडुनोव

यह एक दिलचस्प दावा है। क्या आपके पास एसटीएल कंटेनर बनाम कोको कंटेनर वर्गों की गति लाभ के बारे में एक लेख का लिंक है?
सेडियन एलियन

यहाँ NSCFArray बनाम std :: वेक्टर पर एक दिलचस्प पढ़ा है: वेक्टर: ridiculousfish.com/blog/archives/2005/12/23/array अपनी पोस्ट में उदाहरण में, सबसे बड़ा नुकसान (आम तौर पर) एक objc ऑब्जेक्ट प्रतिनिधित्व तत्व बनाने (जैसे) है , NSValue, NSData, या Objc प्रकार जिसमें मेगापॉइंट होते हैं, को रेफरी-काउंटेड सिस्टम में आवंटन और सम्मिलन की आवश्यकता होती है)। आप वास्तव में सेडेट एलियन के दृष्टिकोण का उपयोग करके एक विशेष सीएफअरे में मेगापॉइंट को स्टोर करने से बच सकते हैं जो कि अलग-अलग आवंटित मेगापॉइंट्स के एक अलग बैकिंग स्टोर का उपयोग करता है (हालांकि न तो उदाहरण उस दृष्टिकोण को दिखाता है)। (cont)
जस्टिन डिक

लेकिन फिर वेक्टर (या अन्य stl प्रकार) बनाम NSCFArray का उपयोग करके डायनामिक डिस्पैच के लिए अतिरिक्त ओवरहेड, अतिरिक्त फ़ंक्शन कॉल जो कि इनबिल्ड नहीं हैं, एक टन प्रकार की सुरक्षा है, और ऑप्टिमाइज़र के किक करने के कई मौके हैं ... लेख सिर्फ सम्मिलित करने, पढ़ने, चलने, हटाने पर केंद्रित है। संभावना है, आपको 16 बाइट संरेखित सी-सरणी से कोई तेज़ नहीं मिलेगा Megapoint pt[8];- यह सी ++ में एक विकल्प है, और विशेष सी ++ कंटेनर (जैसे, std::array) - यह भी ध्यान दें कि उदाहरण विशेष संरेखण को नहीं जोड़ता है (16 बाइट्स चुना गया था क्योंकि यह मेगापॉइंट का आकार है)। (cont)
जस्टिन

std::vectorइसमें थोड़ी मात्रा में ओवरहेड जोड़ दिया जाएगा, और एक आवंटन (यदि आपको पता है कि आपको आकार की आवश्यकता होगी) ... लेकिन यह 99.9% से अधिक मामलों की आवश्यकता के अनुसार धातु के करीब है। आम तौर पर, आप केवल एक वेक्टर का उपयोग करेंगे जब तक कि आकार तय नहीं हो जाता है या एक उचित अधिकतम नहीं होता है।
जस्टिन

0

NSArray में c संरचना को रखने की कोशिश करने के बजाय आप उन्हें NSData या NSMutableData में ac अरेंजमेंट के रूप में रख सकते हैं। उन्हें एक्सेस करने के लिए आप ऐसा करेंगे

const struct MyStruct    * theStruct = (const struct MyStruct*)[myData bytes];
int                      value = theStruct[2].integerNumber;

या फिर सेट करने के लिए

struct MyStruct    * theStruct = (struct MyStruct*)[myData mutableBytes];
theStruct[2].integerNumber = 10;

0

एक NSValue का उपयोग करते हुए, Obj-C ऑब्जेक्ट के रूप में स्ट्रक्चर्स को स्टोर करने के लिए ठीक काम करता है, आप NSArchiver / NSKeyedArchiver के साथ एक स्ट्रक्चर वाले NSValue को एनकोड नहीं कर सकते। इसके बजाय, आपको व्यक्तिगत संरचना सदस्यों को सांकेतिक शब्दों में बदलना होगा ...

देखें एप्पल के अभिलेखागार और serializations प्रोग्रामिंग गाइड> संरचनाएं और बिट फील्ड्स


0

अपनी संरचना के लिए आप एक विशेषता जोड़ सकते हैं objc_boxableऔर @()अपनी संरचना को बिना कॉल किए NSValue उदाहरण में डालने के लिए सिंटैक्स का उपयोग कर सकते हैं valueWithBytes:objCType::

typedef struct __attribute__((objc_boxable)) _Megapoint {
    float   w,x,y,z;
} Megapoint;

NSMutableArray<NSValue*>* points = [[NSMutableArray alloc] initWithCapacity:10];
for (int i = 0; i < 10; i+= 1) {
    Megapoint mp1 = {i + 1.0, i + 2.0, i + 3.0, i + 4.0};
    [points addObject:@(mp1)];//@(mp1) creates NSValue*
}

Megapoint unarchivedPoint;
[[points lastObject] getValue:&unarchivedPoint];
//or
// [[points lastObject] getValue:&unarchivedPoint size:sizeof(Megapoint)];

-2

एक ओबज सी ऑब्जेक्ट कुछ जोड़ा तत्वों के साथ बस एक सी संरचना है। तो बस एक कस्टम वर्ग बनाएं और आपके पास सी संरचना का प्रकार होगा जो एक NSArray की आवश्यकता है। कोई भी C संरचना जिसमें अतिरिक्त cruft नहीं है जो NSObject में शामिल है उसके C संरचना में एक NSArray के लिए अपचनीय होगा।

एक आवरण के रूप में NSData का उपयोग करना केवल संरचना की एक प्रति संग्रहीत करना हो सकता है और मूल संरचनाओं को नहीं, अगर इससे आपको कोई फर्क पड़ता है।


-3

जानकारी को संग्रहीत करने के लिए आप सी-स्ट्रक्चर के अलावा अन्य NSObject कक्षाओं का उपयोग कर सकते हैं। और आप आसानी से उस NSObject को NSArray में स्टोर कर सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.