2009-09-22 9 views
104

मुझे एक कस्टम ऑब्जेक्ट की गहरी प्रतिलिपि बनाने की आवश्यकता है जिसमें इसकी अपनी वस्तुएं हों। मैं एनएससीपीआईइंग और एनएससीपीओब्जेक्ट का उपयोग कैसे करें, इस बारे में थोड़ा उलझन में हूं और थोड़ा उलझन में हूं। क्या कोई मेरी वहां मदद करेगा? पढ़ने के लिए धन्यवाद!उद्देश्य में किसी ऑब्जेक्ट को प्रतिलिपि बनाने के लिए कैसे करें

+1

महान [ट्यूटोरियल] (http://www.techotopia.com/index.php/Copying_Objects_in_Objective-C) प्रतिलिपि को समझने के लिए, mutableCopy और copyWithZone – horkavlna

उत्तर

182

हमेशा संदर्भ प्रकारों के साथ, "प्रतिलिपि" के दो विचार हैं। मुझे यकीन है कि आप उन्हें जानते हैं, लेकिन पूर्णता के लिए।

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

आप उत्तरार्द्ध चाहते हैं। यदि यह आपकी अपनी वस्तुओं में से एक है, तो आपको बस प्रोटोकॉल एनएसपीपीआईइंग और कार्यान्वित करने की आवश्यकता है - (आईडी) copyWithZone: (NSZone *) जोन। आप जो कुछ भी चाहते हैं उसे करने के लिए स्वतंत्र हैं; हालांकि विचार यह है कि आप अपनी वास्तविक प्रतिलिपि बनाते हैं और इसे वापस कर देते हैं। गहरी प्रतिलिपि बनाने के लिए, आप अपने सभी क्षेत्रों पर copyWithZone को कॉल करते हैं। एक साधारण उदाहरण

@interface YourClass : NSObject <NSCopying> 
{ 
    SomeOtherObject *obj; 
} 

// In the implementation 
-(id)copyWithZone:(NSZone *)zone 
{ 
    // We'll ignore the zone for now 
    YourClass *another = [[YourClass alloc] init]; 
    another.obj = [obj copyWithZone: zone]; 

    return another; 
} 
+0

लेकिन आप इसे कॉपी करने के लिए जिम्मेदार प्रतिलिपि ऑब्जेक्ट प्राप्तकर्ता बना रहे हैं! क्या आपको इसे 'ऑटोोरलीज' नहीं करना चाहिए, या क्या मुझे यहां कुछ याद आ रहा है? – bobobobo

+29

@bobobobo: नहीं, उद्देश्य-सी स्मृति का मौलिक नियम प्रबंधन है: यदि आप इसे किसी विधि का उपयोग करते हैं, जिसका नाम "एलोक" या "नया" से शुरू होता है या "प्रतिलिपि" होता है, तो आप किसी ऑब्जेक्ट का स्वामित्व लेते हैं। 'copyWithZone:' इस मानदंड को पूरा करता है, इसलिए इसे किसी ऑब्जेक्ट को बरकरार रखना होगा +1 की गिनती –

+1

@Adam क्या 'allocWithZone' के बजाय 'alloc' का उपयोग करने का कोई कारण है: क्योंकि ज़ोन पारित किया गया था I एन? – Richard

22

एप्पल प्रलेखन

A subclass version of the copyWithZone: method should send the message to super first, to incorporate its implementation, unless the subclass descends directly from NSObject.

, मौजूदा जवाब

@interface YourClass : NSObject <NSCopying> 
{ 
    SomeOtherObject *obj; 
} 

// In the implementation 
-(id)copyWithZone:(NSZone *)zone 
{ 
    YourClass *another = [super copyWithZone:zone]; 
    another.obj = [obj copyWithZone: zone]; 

    return another; 
} 
+1

चूंकि आपका क्लास सीधे NSObject से उतरता है, मुझे नहीं लगता कि यह आवश्यक है – Mike

+2

अच्छा बिंदु, लेकिन इसका एक सामान्य नियम है, यदि यह एक लंबी कक्षा पदानुक्रम के मामले में है। –

+8

मुझे एक त्रुटि मिली: 'NSObject' के लिए कोई दृश्य @interface 'चयनकर्ता' copyWithZone: ''की घोषणा नहीं करता है। मुझे लगता है कि यह केवल तभी जरूरी है जब हम किसी अन्य कस्टम क्लास से विरासत में हों जो 'copyWithZone' – Sam

2
another.obj = [obj copyWithZone: zone]; 

मुझे लगता है कि में जोड़ने के लिए है कि इस लाइन स्मृति रिसाव का कारण बनता है, तो आप क्योंकि पहुँच कहते है संपत्ति के माध्यम से obj पर (मुझे लगता है) retain के रूप में घोषित किया गया है। तो, गिनती को बनाए रखें संपत्ति और copyWithZone द्वारा बढ़ाया जाएगा।

मेरा मानना ​​है कि यह होना चाहिए:

another.obj = [[obj copyWithZone: zone] autorelease]; 

या:

SomeOtherObject *temp = [obj copyWithZone: zone]; 
another.obj = temp; 
[temp release]; 
+0

नहीं, विधियों के आवंटन, प्रतिलिपि, mutableCopy, नए गैर-autoreleased वस्तुओं को वापस करना चाहिए। – kovpas

+0

@ कोवपास, क्या आप निश्चित हैं, कि आप मुझे सही समझते हैं? मैं लौटे ऑब्जेक्ट के बारे में बात नहीं कर रहा हूं, मैं इसके डेटा फ़ील्ड के बारे में बात कर रहा हूं। –

+0

हाँ, मेरे बुरे, क्षमा करें। क्या आप कृपया अपना जवाब किसी भी तरह संपादित कर सकते हैं ताकि मैं घटा सकूं? :)) – kovpas

19

मुझे नहीं है कि कोड और मेरा बीच diference पता है, लेकिन, मुझे लगता है कि समाधान के साथ समस्या है, तो मैं एक पढ़ा थोड़ा और पाया और पाया कि हमें इसे वापस करने से पहले वस्तु को सेट करना होगा। मैं की तरह

#import <Foundation/Foundation.h> 

@interface YourObject : NSObject <NSCopying> 

@property (strong, nonatomic) NSString *nombre;//nombre del medicamento 
@property (strong, nonatomic) NSString *linea;//linea a la que pertenece 
@property (strong, nonatomic) NSMutableString *tags;//palabras por las que se puede encontrar en el buscador 
@property (strong, nonatomic) NSString *htmlSource;//código html para mostrar su contenido 
@property (strong, nonatomic) NSMutableString *obj; 

-(id) copyWithZone: (NSZone *) zone; 

@end 


@implementation YourObject 


-(id) copyWithZone: (NSZone *) zone 
{ 
    YourObject *copy = [[YourObject allocWithZone: zone] init]; 

    [copy setNombre: self.nombre]; 
    [copy setLinea: self.linea]; 
    [copy setTags: self.tags]; 
    [copy setHtmlSource: self.htmlSource]; 

    return copy; 
} 

कुछ मैं इस सवाल का जवाब कारण रखो मतलब है, मैं इस मुद्दे के साथ समस्याओं का एक बहुत कुछ है, और मैं के बारे में क्यों! कोई सुराग नहीं है, मैं अंतर पता नहीं है, लेकिन यह काम और हो सकता है है उपयोगी हो सकता है:)

0

कॉपी करने के लिए -> ऑपरेटर का भी उपयोग किया जाता है। उदाहरण के लिए:

-(id)copyWithZone:(NSZone*)zone 
{ 
    MYClass* copy = [MYClass new]; 
    copy->_property1 = self->_property1; 
    ... 
    copy->_propertyN = self->_propertyN; 
    return copy; 
} 

यहां तर्क यह है कि परिणामी प्रतिलिपि बनाई गई वस्तु को मूल वस्तु की स्थिति को प्रतिबिंबित करना चाहिए। "।"ऑपरेटर साइड इफेक्ट्स पेश कर सकता है क्योंकि यह एक गेटर्स को कॉल करता है जिसमें बदले में तर्क हो सकता है।

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

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