سؤال

ماهو الفرق بين copy و mutableCopy عند استخدامها في أي NSArray أو NSMutableArray?

هذا فهمي هل هذا صحيح؟

// ** NSArray **
NSArray *myArray_imu = [NSArray  arrayWithObjects:@"abc", @"def", nil];

// No copy, increments retain count, result is immutable
NSArray *myArray_imuCopy = [myArray_imu copy];

// Copys object, result is mutable 
NSArray *myArray_imuMuta = [myArray_imu mutableCopy];

// Both must be released later

// ** NSMutableArray **
NSMutableArray *myArray_mut = [NSMutableArray arrayWithObjects:@"A", @"B", nil];

// Copys object, result is immutable
NSMutableArray *myArray_mutCopy = [myArray_mut copy];

// Copys object, result is mutable
NSMutableArray *myArray_mutMuta = [myArray_mut mutableCopy];

// Both must be released later
هل كانت مفيدة؟

المحلول

copy و mutableCopy يتم تعريفها في بروتوكولات مختلفة (NSCopying و NSMutableCopying, ، على التوالي)، و NSArray يتوافق مع كليهما. mutableCopy يتم تعريفه ل NSArray (ليس فقط NSMutableArray) ويسمح لك بإجراء نسخة قابلة للتغيير من صفيف ثابتة في الأصل:

// create an immutable array
NSArray *arr = [NSArray arrayWithObjects: @"one", @"two", @"three", nil ];

// create a mutable copy, and mutate it
NSMutableArray *mut = [arr mutableCopy];
[mut removeObject: @"one"];

ملخص:

  • يمكنك الاعتماد على نتيجة mutableCopy أن تكون قابلة للتغيير، بغض النظر عن النوع الأصلي. في حالة الصفائف، يجب أن تكون النتيجة NSMutableArray.
  • أنت لا تستطيع تعتمد على نتيجة copy أن تكون قابلة للتغيير! copyجي NSMutableArray مايو عودة NSMutableArray, ، لأن هذا هو الطبقة الأصلية، ولكن copyجي أي تعسفي NSArray مثيل لن.

يحرر: أعد قراءة التعليمات البرمجية الأصلية في ضوء إجابة مارك بيسي. عند إنشاء نسخة من صفيفك، بالطبع لا يزال بإمكانك تعديل الأصل بغض النظر عن ما تفعله مع النسخة. copy ضد mutableCopy يؤثر على ما إذا كان صفيف جديد هو قابلة للتغيير.

تحرير 2: إصلاح بلدي (خطأ) افتراض ذلك NSMutableArray -copy سوف يعود NSMutableArray.

نصائح أخرى

أعتقد أنك يجب أن تكون قد أسيء تفسير كيفية عمل نسخة وموتايتاقة. في مثالتك الأولى، تعد Myarriay_copy نسخة ثابتة من Myarray. بعد أن قامت بالنسخة، يمكنك معالجة محتويات Myarray الأصلية، ولا تؤثر على محتويات myarray_copy.

في المثال الثاني، تقوم بإنشاء نسخة مطولة من Myarray، مما يعني أنه يمكنك تعديل إما نسخة من الصفيف، دون التأثير على الآخر.

إذا قمت بتغيير المثال الأول لمحاولة إدراج / إزالة الكائنات من myarray_copy، فافشل، تماما كما تريد.


ربما التفكير في حالة الاستخدام النموذجية سوف تساعد. غالبا ما تكون الحالة التي قد تكتب طريقة تأخذ NSArray * المعلمة، وتخزينها أساسا للاستخدام لاحقا. يمكنك القيام بهذه الطريقة:

- (void) doStuffLaterWith: (NSArray *) objects {
  myObjects=[objects retain];
}

... ولكن بعد ذلك، لديك المشكلة التي يمكن استدعاء الطريقة مع nsmutablerray مثل الوسيطة. قد يتم التعامل مع التعليمات البرمجية التي تم إنشاؤها على صفيفها بين متى يتم استدعاء طريقة dostufflaterwith: وعندما تحتاج لاحقا إلى استخدام القيمة. في تطبيق متعدد الخيوط، يمكن حتى تغيير محتويات الصفيف بينما كنت تكرار بشأنها, ، والتي يمكن أن تسبب بعض الأخطاء المثيرة للاهتمام.

إذا كنت تفعل ذلك بدلا من ذلك:

- (void) doStuffLaterWith: (NSArray *) objects {
  myObjects=[objects copy];
}

..ثمن النسخة تنشئ لقطة من محتويات الصفيف في وقت استدعاء الطريقة.

تقوم طريقة "النسخ" بإرجاع الكائن الذي تم إنشاؤه عن طريق تطبيق بروتوكولات Nscopying CopyWithZone:

إذا قمت بإرسال رسالة نسخ nsstring:

NSString* myString;

NSString* newString = [myString copy];

ستكون قيمة الإرجاع nsstring (غير قابلة للتغيير)


تقوم طريقة MutableCopy بإرجاع الكائن الذي تم إنشاؤه عن طريق تطبيق MutablecopyWithzone الخاص بالبروتوكول NSMutableCoPypzone:

عبر الارسال:

NSString* myString;

NSMutableString* newString = [myString mutableCopy];

قيمة العودة إرادة أن تكون متغيرة.


في جميع الحالات، يجب أن ينفذ الكائن البروتوكول، مما يدل على إنشاء كائن نسخ جديد وإرجاعه إليك.


في حالة NSArray، هناك مستوى إضافي من التعقيد فيما يتعلق بالنسخ الضحل والعميق.

لن يتم نسخ نسخة ضحلة من NSArray فقط المراجع إلى كائنات الصفيف الأصلي ووضعها في الصفيف الجديد.

النتيجة هي أن:

NSArray* myArray;

NSMutableArray* anotherArray = [myArray mutableCopy];

[[anotherArray objectAtIndex:0] doSomething];

سيؤثر أيضا على الكائن في الفهرس 0 في الصفيف الأصلي.


سنسخ نسخة عميقة في الواقع الكائنات الفردية الموجودة في الصفيف. يتم ذلك عن طريق إرسال كل كائن فردي "copywithzone:".

NSArray* myArray;

NSMutableArray* anotherArray = [[NSMutableArray alloc] initWithArray:myArray
                                                       copyItems:YES];

تم تحريره لإزالة افتراضي الخطأ حول نسخ كائن قابل للتغيير

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

سيصنع anotherArray وهي نسخة من oldArray إلى 2 مستويات عميقة. إذا كان كائن oldArray هي صفيف. وهو عموما الحالة في معظم التطبيقات.

حسنا إذا كنا بحاجة إلى نسخة عميقة حقيقية يمكننا استخدام،

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

هذا من شأنه أن يضمن أن يتم نسخ جميع المستويات بالفعل الاحتفاظ بقدرة الصوت الأصلية في كل مستوى.

روبرت كلارينس د المعدة، بنغالور، الهند.

أنت تسمون AddObject و RephengoBjectATIndex على الصفيف الأصلي، بدلا من النسخة الجديدة التي قمت بها. استدعاء النسخ VS Mutablecopy فقط تؤثر فقط على تغيير النسخة الجديدة من الكائن، وليس الكائن الأصلي.

أن تذكرها ببساطة،

  • نسخ إرجاع نسخة ثابتة (لا يمكن تعديلها) من الصفيف،
  • تعيد Mutablecopy نسخة قابلة للتغيير (يمكن تعديلها) نسخة من الصفيف.

تعني النسخة (في كلتا الحالتين) أن تحصل على صفيف جديد "مأهول" مع مراجع كائن إلى الصفيف الأصلي (أي الكائنات نفسها (الأصلية) المشار إليها في النسخ.

إذا قمت بإضافة كائنات جديدة إلى Mutablecopy، فهي فريدة من نوعها إلى Mutablecopy. إذا قمت بإزالة الكائنات من Mutablecopy، تتم إزالةها من الصفيف الأصلي.

فكر في النسخة في كلتا الحالتين، كقسم لقطة في الوقت المناسب من الصفيف الأصلي في وقت إنشاء النسخة.

افترض

NSArray *A = xxx; // A with three NSDictionary objects
NSMutableArray *B = [A mutableCopy]; 

محتوى B هو كائن nsdictionary لا nsmutabledictionary، هل صحيح؟

-(id)copy always returns a immutable one & -(id)mutableCopy always returns a mutable object,that's it.

عليك أن تعرف نوع الإرجاع من الأشياء التي نسخ هذه، بينما تعلن الكائن الجديد الذي سيتم تعيين قيمة الإرجاع من نوعه غير قابل للتغيير أو قابل للتغيير، وإلا سيعرض برنامج التحويل البرمجي الخاص بك خطأ.

لا يمكن تعديل الكائن الذي تم نسخه باستخدام المرء الجديد، فهي كائنات مختلفة تماما الآن.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top