একটি এনএসআরিকে গভীরভাবে অনুলিপি করা হচ্ছে


119

এমন কোনও বিল্ট-ইন ফাংশন রয়েছে যা আমাকে একটি গভীর অনুলিপি করতে দেয় NSMutableArray?

আমি চারপাশে তাকালাম, কিছু লোক বলেছেন [aMutableArray copyWithZone:nil]গভীর কপি হিসাবে কাজ করে। তবে আমি চেষ্টা করেছি এবং এটি একটি অগভীর অনুলিপি বলে মনে হচ্ছে।

এখনই আমি ম্যানুয়ালি একটি forলুপ দিয়ে অনুলিপিটি করছি :

//deep copy a 9*9 mutable array to a passed-in reference array

-deepMuCopy : (NSMutableArray*) array 
    toNewArray : (NSMutableArray*) arrayNew {

    [arrayNew removeAllObjects];//ensure it's clean

    for (int y = 0; y<9; y++) {
        [arrayNew addObject:[NSMutableArray new]];
        for (int x = 0; x<9; x++) {
            [[arrayNew objectAtIndex:y] addObject:[NSMutableArray new]];

            NSMutableArray *aDomain = [[array objectAtIndex:y] objectAtIndex:x];
            for (int i = 0; i<[aDomain count]; i++) {

                //copy object by object
                NSNumber* n = [NSNumber numberWithInt:[[aDomain objectAtIndex:i] intValue]];
                [[[arrayNew objectAtIndex:y] objectAtIndex:x] addObject:n];
            }
        }
    }
}

তবে আমি একটি ক্লিনার, আরও সংক্ষিপ্ত সমাধান চাই।


44
@ জেনেরিক্রিচ গভীর এবং অগভীর অনুলিপিগুলি সফ্টওয়্যার বিকাশে বেশ ভাল সংজ্ঞায়িত শর্তাদি। গুগল ডট কম সহায়তা করতে পারে
অ্যান্ড্রু গ্রান্ট

1
কিছু বিভ্রান্তির কারণ হ'ল -copyম্যাক ওএস এক্স 10.4 এবং 10.5 এর মধ্যে অপরিবর্তনীয় সংগ্রহগুলি নিয়ে আচরণের পরিবর্তন হয়েছে: বিকাশকারী.অ্যাপলস / লিবারি / ম্যাক / রিলিজ নোটস / কোকোয়া / (("অপরিষ্কার সংগ্রহ এবং অনুলিপি আচরণ" -এ স্ক্রোল করুন)
ব্যবহারকারী 102008

1
@ অ্যান্ড্রুগ্র্যান্ট আরও চিন্তাভাবনা এবং সম্মানের সাথে, আমি একমত নই যে গভীর অনুলিপি একটি সুস্পষ্ট সংজ্ঞাযুক্ত শব্দ। আপনি কোন উত্সটি পড়েছেন তার উপর নির্ভর করে, নেস্টেড ডেটা স্ট্রাকচারগুলিতে সীমাহীন পুনরাবৃত্তি একটি 'ডিপ কপি' অপারেশনের প্রয়োজন কিনা তা পরিষ্কার it's অন্য কথায়, আপনি একটি অনুলিপি উত্তর পাবেন যে কোনও অনুলিপি অপারেশন যা একটি নতুন অবজেক্ট তৈরি করে যার সদস্যরা মূল বস্তুর সদস্যদের অগভীর অনুলিপিগুলি একটি 'গভীর অনুলিপি' অপারেশন কিনা। এর কিছু আলোচনার জন্য স্ট্যাকওভারফ্লো.com/ a/ 6183597/1709587 দেখুন (একটি জাভা প্রসঙ্গে, তবে এটি সমস্ত একই প্রাসঙ্গিক)।
মার্ক আমেরিকা 1'13

@ অ্যান্ড্রুগ্র্যান্ট আমাকে @ মারকআমেরি এবং @ জেনেরিক্রিচের ব্যাক আপ নিতে হবে। একটি গভীর অনুলিপিটি সংজ্ঞায়িত করা হয় যদি কোনও সংগ্রহের মধ্যে ব্যবহার করা মূল শ্রেণি এবং তার সমস্ত উপাদান অনুলিপিযোগ্য হয়। এনএসএরারে (এবং অন্যান্য অবজেক্ট সংগ্রহ) এর ক্ষেত্রে এটি হয় না। যদি কোনও উপাদান বাস্তবায়ন না copyকরে তবে "গভীর অনুলিপি" তে কী রাখা হবে? যদি উপাদানটি অন্য সংগ্রহ copyহয় তবে আসলে একটি অনুলিপি দেয় না (একই শ্রেণীর) class সুতরাং আমি মনে করি এটি নির্দিষ্ট ক্ষেত্রে কপির প্রকারটি নিয়ে তর্ক করা পুরোপুরি বৈধ।
নিকোলাই রুহে

@ নিকোলাইরুহে যদি কোনও উপাদান বাস্তবায়ন না করে NSCopying/ -copyতবে তা অনুলিপিযোগ্য নয় — সুতরাং এটির অনুলিপি করার জন্য আপনার কখনও চেষ্টা করা উচিত নয়, কারণ এটি এমন দক্ষতা নয় যা এটি তৈরি করার জন্য তৈরি করা হয়েছিল। কোকো বাস্তবায়নের ক্ষেত্রে, অনুলিপিযোগ্য অবজেক্টগুলিতে প্রায়শই কিছু সি ব্যাকএন্ডের অবস্থা থাকে যার সাথে তারা আবদ্ধ থাকে, সুতরাং বস্তুর সরাসরি কপি হ্যাক করার কারণে জাতিগত পরিস্থিতি বা আরও খারাপ হতে পারে। সুতরাং "গভীর অনুলিপিটিতে কী দেওয়া হবে" - উত্তর দেওয়ার জন্য একটি আটকানো রেফ আপনি যখন কোনও অ- NSCopyingঅবজেক্ট রাখেন তখন কেবলমাত্র আপনি যে কোনও জায়গায় রাখতে পারেন ।
স্লিপ ডি থম্পসন

উত্তর:


210

গভীর অনুলিপি সম্পর্কে অ্যাপল নথি হিসাবে স্পষ্টভাবে বলা হয়েছে:

আপনার যদি কেবলমাত্র এক-স্তর-গভীর অনুলিপি প্রয়োজন:

NSMutableArray *newArray = [[NSMutableArray alloc] 
                             initWithArray:oldArray copyItems:YES];

উপরের কোডটি একটি নতুন অ্যারে তৈরি করেছে যার সদস্যরা পুরানো অ্যারের সদস্যদের অগভীর অনুলিপিগুলি।

মনে রাখবেন যে আপনার যদি একটি সম্পূর্ণ নেস্টেড ডেটা স্ট্রাকচার গভীরভাবে অনুলিপি করতে হয় - লিঙ্কযুক্ত অ্যাপল ডক্স সত্যিকারের গভীর কপি বলে - তবে এই পদ্ধতির পক্ষে যথেষ্ট হবে না। তার জন্য এখানে অন্যান্য উত্তরগুলি দেখুন।


সঠিক উত্তর বলে মনে হচ্ছে। এপিআই জানিয়েছে যে প্রতিটি উপাদান একটি [এলিমেন্ট কপি উইথজোন:] বার্তা পায় যা আপনি যা দেখছিলেন তা হতে পারে। আপনি যদি সত্যিই দেখছেন যে [এনএসমিটেবলআরে কপি উইথজোন: নীল] প্রেরণ করা গভীর কপি করে না, তবে অ্যারেগুলির একটি অ্যারে এই পদ্ধতিটি ব্যবহার করে সঠিকভাবে অনুলিপি করতে পারে না।
এড মার্টি

7
আমি মনে করি না এটি প্রত্যাশার মতো কাজ করবে। অ্যাপল ডক্স থেকে: copyWithZone ": পদ্ধতি সঞ্চালিত একটি অগভীর কপি । আপনি নির্বিচারে গভীরতা একটি সংগ্রহ, ফ্ল্যাগ প্যারামিটার পৃষ্ঠের নিচে প্রথম স্তরের একজন অপরিবর্তনীয় কপি সঞ্চালন করবে হ্যাঁ ক্ষণস্থায়ী যদি আপনি কোন এর পরিবর্তনশীলতা পাস করে। প্রথম স্তরটি ক্ষতিগ্রস্থ নয় either উভয় ক্ষেত্রেই, সমস্ত গভীর স্তরের পরিবর্তনশীলতা প্রভাবিত হয় না "
জো

7
এটি কোনও গভীর অনুলিপি নয়
দাইজ-দাজন

9
এটি একটি অসম্পূর্ণ উত্তর। এটি এক-স্তরের গভীর অনুলিপিটির ফলাফল। অ্যারের মধ্যে আরও জটিল ধরণের থাকলে এটি একটি গভীর অনুলিপি সরবরাহ করে না।
ক্যামেরন লোয়েল পামার

7
এই করতে একটি গভীর কপি, কিভাবে উপর নির্ভর করে হতে copyWithZone:প্রাপ্তির বর্গ উপর বাস্তবায়িত হয়।
ডিভাইস 1

62

সহজেই এটি করতে আমি জানতে পারি একমাত্র উপায় সংরক্ষণাগারভুক্ত করা এবং তারপরে তাত্ক্ষণিকভাবে আপনার অ্যারেটিকে আর্কাইভ করা। এটি কিছুটা হ্যাকের মতো অনুভূত হয় তবে অনুলিপি সংগ্রহের অনুলিপি সম্পর্কে অ্যাপল ডকুমেন্টেশনে সুস্পষ্টভাবে পরামর্শ দেওয়া হয়েছে , যা বলে:

আপনার যদি সত্যিকারের গভীর অনুলিপি দরকার হয়, যেমন আপনার কাছে অ্যারে থাকে তখন আপনি সংরক্ষণাগার সংগ্রহ করতে পারেন এবং তারপরে সংগ্রহটি আর্কাইভ করতে পারেন, সমস্ত বিষয়বস্তু এনএসকোডিং প্রোটোকলের সাথে সামঞ্জস্য করে provided এই কৌশলটির একটি উদাহরণ তালিকা 3 এ দেখানো হয়েছে।

তালিকা 3 একটি সত্য গভীর অনুলিপি

NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:
          [NSKeyedArchiver archivedDataWithRootObject:oldArray]];

ক্যাচটি হ'ল আপনার অবজেক্টটি অবশ্যই এনএসকোডিং ইন্টারফেসটিকে সমর্থন করবে, যেহেতু এটি ডেটা সঞ্চয় / লোড করতে ব্যবহৃত হবে।

সুইফট 2 সংস্করণ:

let trueDeepCopyArray = NSKeyedUnarchiver.unarchiveObjectWithData(
    NSKeyedArchiver.archivedDataWithRootObject(oldArray))

12
যদি আপনার অ্যারেগুলি বড় হয় তবে এনএসআরচিভার এবং এনএসউনারকিভার ব্যবহার করা খুব ভারী সমাধানের কার্যকারিতা অনুসারে। জেনেরিক এনএসআর ক্যাটাগরি পদ্ধতি যা এনএসকোপিং প্রোটোকল ব্যবহার করে তা লেখার কৌশলটি কার্যকর হবে, ফলে অপরিবর্তনীয় বস্তুর একটি সহজ 'রক্ষণাবেক্ষণ' এবং পরিবর্তনীয়গুলির সত্যিকারের 'অনুলিপি' তৈরি হবে।
নিকিতা ঝুক

ব্যয় সম্পর্কে সতর্ক হওয়া ভাল, তবে initWithArray:copyItems:পদ্ধতিতে ব্যবহৃত এনএসকোপিংয়ের চেয়ে এনএসকোডিং কি সত্যই বেশি ব্যয়বহুল হবে ? এই সংরক্ষণাগারটি / আর্কাইভ সংরক্ষণের কাজটি বেশ কার্যকর বলে মনে হচ্ছে, কতগুলি নিয়ন্ত্রণ শ্রেণি এনএসকোডিংয়ের সাথে মেনে চলে তবে এনএসকোপিংয়ের সাথে নয়।
Wienke

আমি আপনাকে সুপারিশ করব যে আপনি কখনও এই পদ্ধতির ব্যবহার করবেন না। ক্রমিকায়ন কেবল মেমরি অনুলিপি করার চেয়ে দ্রুত হয় না faster
ব্রেট

1
আপনার যদি কাস্টম অবজেক্টস থাকে তবে এনএসকোডিং প্রোটোকলটি মেনে চলার জন্য এনকোডউইথকোডার এবং ইনটুইটথ কোডার বাস্তবায়ন করতে ভুলবেন না।
ব্যবহারকারী523234

স্পষ্টতই সিরিয়ালাইজেশন ব্যবহার করার সময় প্রোগ্রামারের বিচক্ষণতার দৃ strongly় পরামর্শ দেওয়া হয়।
ভিএইচ-এনজেডজেড

34

ডিফল্টরূপে অনুলিপি অগভীর অনুলিপি দেয়

এটি কারণ কলিং copyএকই হিসাবে copyWithZone:NULLডিফল্ট অঞ্চলে অনুলিপি হিসাবে পরিচিত। copyকল একটি গভীর কপি ফলে না। বেশিরভাগ ক্ষেত্রে এটি আপনাকে অগভীর অনুলিপি দেবে, তবে কোনও ক্ষেত্রে এটি শ্রেণীর উপর নির্ভর করে। পুঙ্খানুপুঙ্খ আলোচনার জন্য আমি সংকলন প্রোগ্রামিং বিষয়গুলির প্রস্তাব দিই অ্যাপল বিকাশকারী সাইটে ।

initWithArray: কপিআইটেমস: এক স্তরের গভীর অনুলিপি দেয়

NSArray *deepCopyArray = [[NSArray alloc] initWithArray:someArray copyItems:YES];

NSCoding গভীর অনুলিপি সরবরাহ করার জন্য অ্যাপল প্রস্তাবিত উপায়

সত্যিকারের গভীর অনুলিপিটির জন্য (অ্যারের অ্যারে) আপনার প্রয়োজন হবে NSCodingএবং অবজেক্টটি সংরক্ষণাগারভুক্ত / সংরক্ষণাগারভুক্ত করবেন:

NSArray *trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:oldArray]];

1
এটা সঠিক। মেমরি, কর্মক্ষমতা সম্পর্কে জনপ্রিয়তা বা অকাল-অপ্টিমাইজড এজ-কেস নির্বিশেষে। একদিকে যেমন, গভীর অনুলিপিটির জন্য এই সার্-ডার্সার হ্যাকটি অন্য অনেক ভাষার পরিবেশে ব্যবহৃত হয়। আপত্তি ছাড়ো না থাকলে, এটি মূল থেকে সম্পূর্ণ পৃথক একটি ভাল গভীর অনুলিপি দেয়।

1
এখানে একটি কম rotable অ্যাপল ডক ইউআরএল বিকাশকারী।

7

স্বৈরশাসনের জন্য

NSMutableDictionary *newCopyDict = (NSMutableDictionary *)CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFDictionaryRef)objDict, kCFPropertyListMutableContainers);

অ্যারের জন্য

NSMutableArray *myMutableArray = (NSMutableArray *)CFPropertyListCreateDeepCopy(NULL, arrData, kCFPropertyListMutableContainersAndLeaves);


4

না, এর জন্য ফ্রেমওয়ার্কগুলিতে কিছু অন্তর্নির্মিত নেই। কোকো সংগ্রহগুলি অগভীর অনুলিপিগুলিকে সমর্থন করে (সাথে copyবা এর সাথেarrayWithArray: পদ্ধতিগুলির সাহায্যে) সমর্থন করে তবে গভীর অনুলিপি ধারণা সম্পর্কেও কথা বলেন না।

এটি কারণ "গভীর অনুলিপি" আপনার নিজস্ব কাস্টম অবজেক্টগুলি সহ আপনার সংগ্রহের বিষয়বস্তুগুলি শুরু হওয়ার সাথে সাথে সংজ্ঞা দেওয়া কঠিন হতে শুরু করে। "গভীর কপি" এর অর্থ কি যে বস্তুর গ্রাফে বস্তু একটি অনন্য রেফারেন্স আপেক্ষিক প্রত্যেক মূল বস্তু গ্রাফে বস্তু?

যদি কিছু অনুমানমূলক NSDeepCopyingপ্রোটোকল থাকে, আপনি এটিকে সেট আপ করতে এবং আপনার সমস্ত বস্তুতে সিদ্ধান্ত নিতে পারতেন, তবে দুর্ভাগ্যক্রমে এটি হয়নি। আপনি যদি নিজের গ্রাফের বেশিরভাগ অবজেক্টগুলিকে নিয়ন্ত্রণ করেন তবে আপনি নিজেই এই প্রোটোকল তৈরি করতে এবং এটি বাস্তবায়ন করতে পারতেন, তবে আপনার প্রয়োজন অনুসারে ফাউন্ডেশন ক্লাসে একটি বিভাগ যুক্ত করা দরকার।

@ অ্যান্ড্রুগ্র্যান্টের উত্তর কী-আর্কাইভ / আনার্কাইভিংয়ের ব্যবহারের পরামর্শ দেয় তা স্বেচ্ছাসেবী বস্তুগুলির জন্য এটি অর্জনের একটি কলুষিত কিন্তু সঠিক এবং পরিষ্কার উপায়। এই বইটি এখনও পর্যন্ত গেছে তাই গভীরভাবে অনুলিপি সমর্থন করতে ঠিক এমনটি করে এমন সমস্ত বস্তুতে একটি বিভাগ যুক্ত করার পরামর্শ দেয়


2

JSON সামঞ্জস্যপূর্ণ ডেটার জন্য গভীর অনুলিপি অর্জন করার চেষ্টা করা থাকলে আমার একটি কার্যকারিতা রয়েছে।

কেবলমাত্র নিতে NSDataএর NSArrayব্যবহার NSJSONSerializationএবং তারপর JSON সামগ্রী পুনঃ, এই একটি সম্পূর্ণ নতুন এবং তাজা কপি তৈরি করবে NSArray/NSDictionaryতাদের নতুন মেমরি রেফারেন্স সঙ্গে।

তবে নিশ্চিত হয়ে নিন যে এনএসআরাই / এনএসডি অভিধান এবং তাদের বাচ্চাদের অবশ্যই জেএসএন সিরিয়ালযোগ্য হতে হবে।

NSData *aDataOfSource = [NSJSONSerialization dataWithJSONObject:oldCopy options:NSJSONWritingPrettyPrinted error:nil];
NSDictionary *aDictNewCopy = [NSJSONSerialization JSONObjectWithData:aDataOfSource options:NSJSONReadingMutableLeaves error:nil];

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