কীভাবে কোনও অবজেক্ট-সি-তে অনুলিপি করবেন


112

আমাকে একটি কাস্টম অবজেক্টের গভীর অনুলিপি করতে হবে যার নিজস্ব জিনিস রয়েছে। আমি আশেপাশে পড়ছি এবং এনএসকোপিং কীভাবে উত্তরাধিকারী হবে এবং এনএসকপিওজেক্ট কীভাবে ব্যবহার করতে হয় সে সম্পর্কে কিছুটা বিভ্রান্ত হয়ে পড়েছি।


1
মহান টিউটোরিয়াল বোঝার কপি, mutableCopy এবং copyWithZone জন্য
horkavlna

উত্তর:


192

রেফারেন্স প্রকারের মতো সর্বদা, "অনুলিপি" এর দুটি ধারণা রয়েছে। আমি নিশ্চিত আপনি এগুলি জানেন তবে সম্পূর্ণতার জন্য।

  1. কিছুটা কপি। এটিতে আমরা কেবল মেমরি বিটের জন্য কিছুটা কপি করি - এনএসকপিওবজেক্ট এটি করে does প্রায় সর্বদা, এটি আপনি চান তা নয়। বস্তুর অভ্যন্তরীণ স্থিতি, অন্যান্য বস্তু ইত্যাদি রয়েছে এবং প্রায়শই অনুমান করা হয় যে তারা কেবলমাত্র সেই ডেটাটির রেফারেন্স রাখে। বিটওয়াইস অনুলিপিগুলি এই অনুমানটি ভঙ্গ করে।
  2. একটি গভীর, যৌক্তিক অনুলিপি। এটিতে আমরা অবজেক্টটির একটি অনুলিপি তৈরি করি, তবে বাস্তবে কিছুটা হলেও তা না করে - আমরা এমন একটি বস্তু চাই যা সমস্ত উদ্দেশ্য এবং উদ্দেশ্যে একই রকম আচরণ করে, তবে (প্রয়োজনীয়ভাবে) মূলটির একটি স্মৃতি-অভিন্ন ক্লোন নয় - অবজেক্টিভ সি ম্যানুয়াল এটিকে একটি আসলটিকে আসল থেকে "কার্যকরীভাবে স্বতন্ত্র" বলে। যেহেতু এই "বুদ্ধিমান" অনুলিপিগুলি তৈরি করার পদ্ধতিগুলি শ্রেণী থেকে এক শ্রেণিতে পরিবর্তিত হয়, তাই আমরা বস্তুগুলিকে সেগুলি সম্পাদন করতে বলি। এটি এনএসকোপিং প্রোটোকল।

আপনি পরেরটি চান। এটি যদি আপনার নিজস্ব একটি জিনিস হয় তবে আপনার কেবল প্রোটোকল এনএসকোপি করা এবং বাস্তবায়ন করতে হবে - (আইডি) কপি উইথজোন: (এনএস জোন *) জোন। আপনি যা চান তা করতে নির্দ্বিধায়; যদিও ধারণাটি হ'ল আপনি নিজের একটি আসল অনুলিপি তৈরি করে তা ফিরিয়ে দিন। একটি গভীর অনুলিপি তৈরি করতে আপনি আপনার সমস্ত ক্ষেত্রে কপিরউথজোনকে কল করেছেন। একটি সহজ উদাহরণ

@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;
}

তবে আপনি অনুলিপিযুক্ত অনুলিপিটির প্রাপককে দায়বদ্ধ করছেন! আপনি autoreleaseএটি না করা উচিত, না আমি এখানে কিছু মিস করছি?
bobobobo

30
@ বোবোবো: না, অবজেক্টিভ-সি মেমরি ম্যানেজমেন্টের মূল নিয়মটি হ'ল: আপনি যদি কোনও জিনিসটির নাম "বরাদ্দ" বা "নতুন" দিয়ে শুরু হয় বা "অনুলিপি" সহ এমন একটি পদ্ধতি ব্যবহার করে তৈরি করেন তবে আপনি কোনও বিষয়টির মালিকানা গ্রহণ করেন। copyWithZone:এই মানদণ্ডটি পূরণ করে, সুতরাং এটি অবশ্যই +1 এর বজায় রেখে গণনা সহ কোনও বস্তুকে ফেরত দিতে হবে।
স্টিভ ম্যাডসেন

1
@ অ্যাডাম জোনটি পেরিয়ে যাওয়ার allocপরিবর্তে কি ব্যবহার করার কোনও কারণ আছে allocWithZone:?
রিচার্ড

3
ঠিক আছে, আধুনিক ওএস এক্স ভিত্তিক রানটাইমগুলিতে অঞ্চলগুলি কার্যকরভাবে অব্যবহৃত হয়েছে (অর্থাত আমি মনে করি সেগুলি আক্ষরিক অর্থে কখনই ব্যবহৃত হয় না)। তবে হ্যাঁ, আপনি কল করতে পারেন allocWithZone
অ্যাডাম রাইট


25

অ্যাপল ডকুমেন্টেশন বলছে

কপিরথ উইথজোন: উপ-শ্রেণীর সংস্করণটি সরাসরি এনএসবজেক্ট থেকে অবতরণ না করা পর্যন্ত এর প্রয়োগকরণ সংযুক্ত করার জন্য প্রথমে ম্যাসেজটি সুপারকে প্রেরণ করা উচিত।

বিদ্যমান উত্তর যুক্ত করতে

@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;
}

2
যেহেতু আপনারক্লাস সরাসরি এনএসবজেক্ট থেকে নেমেছে আমি এখানে এটি প্রয়োজনীয় মনে করি না
মাইক

2
ভাল পয়েন্ট, তবে এটি একটি দীর্ঘ নিয়ম, যদি এটি একটি দীর্ঘ শ্রেণীর শ্রেণিবদ্ধতা হয়।
সাকিব সৌদ

8
আমি একটি ত্রুটি করেছেন: No visible @interface for 'NSObject' declares the selector 'copyWithZone:'। আমি অনুমান করি এটি কেবল তখনই প্রয়োজন যখন আমরা প্রয়োগ করি এমন কিছু অন্যান্য কাস্টম ক্লাসের উত্তরাধিকারীcopyWithZone
স্যাম

1
another.obj = [[আপত্তি কপি উইথজোন: জোন] স্বতঃপরে] এনএসবজেক্টের সমস্ত সাবক্লাসের জন্য। এবং আদিম ডেটাটাইপগুলির জন্য আপনি কেবল এগুলি বরাদ্দ করেছেন -> another.someBOOL = self.someBOOL;
hariszaman

@ সাম "এনএসবজেক্ট নিজেই এনএসকোপিং প্রোটোকলকে সমর্থন করে না Sub সাবক্লাসগুলি অবশ্যই প্রোটোকলকে সমর্থন করবে এবং কপি উইথজোন: পদ্ধতিটি প্রয়োগ করবে the এনএসবজেক্ট থেকে। বিকাশকারী
অ্যাপ্লিকেশন

21

আমি সেই কোড এবং আমার মধ্যে পার্থক্য জানি না, তবে সেই সমাধানে আমার সমস্যা আছে, তাই আমি আরও কিছুটা পড়েছি এবং দেখতে পেলাম যে এটিটি ফেরত দেওয়ার আগে আমাদের সেট করতে হবে। আমি এরকম কিছু বোঝাতে চাইছি:

#import <Foundation/Foundation.h>

@interface YourObject : NSObject <NSCopying>

@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSString *line;
@property (strong, nonatomic) NSMutableString *tags;
@property (strong, nonatomic) NSString *htmlSource;
@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.name];
    [copy setLinea: self.line];
    [copy setTags: self.tags];
    [copy setHtmlSource: self.htmlSource];

    return copy;
}

আমি এই উত্তরটি যুক্ত করেছি কারণ এই সমস্যাটি নিয়ে আমার অনেক সমস্যা রয়েছে এবং কেন এটি হচ্ছে তা সম্পর্কে আমার কোনও ধারণা নেই। আমি পার্থক্যটি জানি না, তবে এটি আমার পক্ষে কাজ করছে এবং এটি অন্যের পক্ষেও কার্যকর হতে পারে:)


3
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

অনুলিপি করার জন্য -> অপারেটরেরও ব্যবহার রয়েছে। উদাহরণ স্বরূপ:

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

এখানে যুক্তি হ'ল ফলশ্রুতিযুক্ত অনুলিপি করা বস্তুটি মূল বস্তুর অবস্থা প্রতিফলিত করে। দ্য "." অপারেটর পার্শ্ব প্রতিক্রিয়াগুলির সাথে পরিচয় করিয়ে দিতে পারে কারণ এটি একটি কলকারীদের কল করে যার পরিবর্তে যুক্তি থাকতে পারে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.