ฉันต้องการคัดลอกวัตถุแบบกำหนดเองที่มีวัตถุเป็นของตัวเอง ฉันอ่านมาเรื่อย ๆ และสับสนเล็กน้อยเกี่ยวกับวิธีการสืบทอด NSCopying และวิธีใช้ NSCopyObject
ฉันต้องการคัดลอกวัตถุแบบกำหนดเองที่มีวัตถุเป็นของตัวเอง ฉันอ่านมาเรื่อย ๆ และสับสนเล็กน้อยเกี่ยวกับวิธีการสืบทอด NSCopying และวิธีใช้ NSCopyObject
คำตอบ:
เช่นเคยกับประเภทการอ้างอิงมีแนวคิดเกี่ยวกับ "สำเนา" อยู่สองประการ ฉันแน่ใจว่าคุณรู้จักพวกเขา แต่เพื่อความสมบูรณ์
คุณต้องการอย่างหลัง หากนี่เป็นหนึ่งในออบเจ็กต์ของคุณเองคุณต้องใช้โปรโตคอล NSCopying และใช้งาน - (id) copyWithZone: (NSZone *) zone คุณมีอิสระที่จะทำสิ่งที่คุณต้องการ แม้ว่าแนวคิดนี้คือคุณทำสำเนาตัวเองจริงและส่งคืน คุณเรียก 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;
}
autorelease
หรือฉันขาดอะไรที่นี่?
copyWithZone:
ตรงตามเกณฑ์นี้ดังนั้นจึงต้องส่งคืนวัตถุที่มีจำนวนคงที่ +1
alloc
แทนallocWithZone:
ตั้งแต่ผ่านโซนมา?
allocWithZone
.
เอกสารของ Apple กล่าวว่า
รุ่น subclass ของวิธี copyWithZone: ควรส่งข้อความไปยัง super ก่อนเพื่อรวมการนำไปใช้งานเว้นแต่ว่าคลาสย่อยจะลงมาจาก 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;
}
No visible @interface for 'NSObject' declares the selector 'copyWithZone:'
. ฉันเดาว่าสิ่งนี้จำเป็นเฉพาะเมื่อเรารับช่วงจากคลาสที่กำหนดเองอื่น ๆ ที่ใช้copyWithZone
ฉันไม่รู้ความแตกต่างระหว่างรหัสนั้นกับของฉัน แต่ฉันมีปัญหากับวิธีแก้ปัญหานั้นดังนั้นฉันจึงอ่านอีกเล็กน้อยและพบว่าเราต้องตั้งค่าวัตถุก่อนที่จะส่งคืน ฉันหมายถึงสิ่งที่ชอบ:
#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;
}
ฉันเพิ่มคำตอบนี้เนื่องจากฉันมีปัญหามากมายเกี่ยวกับปัญหานี้และฉันไม่รู้ว่าทำไมจึงเกิดขึ้น ฉันไม่รู้ความแตกต่าง แต่มันใช้ได้ผลสำหรับฉันและอาจเป็นประโยชน์สำหรับคนอื่น ๆ ด้วย :)
another.obj = [obj copyWithZone: zone];
ฉันคิดว่าบรรทัดนี้ทำให้เกิดการรั่วไหลของหน่วยความจำเนื่องจากคุณเข้าถึงobj
ผ่านคุณสมบัติซึ่ง (ฉันถือว่า) ประกาศเป็นretain
. ดังนั้นเก็บนับcopyWithZone
จะเพิ่มขึ้นโดยทรัพย์สินและ
ฉันเชื่อว่ามันควรจะเป็น:
another.obj = [[obj copyWithZone: zone] autorelease];
หรือ:
SomeOtherObject *temp = [obj copyWithZone: zone];
another.obj = temp;
[temp release];
นอกจากนี้ยังมีการใช้ตัวดำเนินการ -> ในการคัดลอก ตัวอย่างเช่น:
-(id)copyWithZone:(NSZone*)zone
{
MYClass* copy = [MYClass new];
copy->_property1 = self->_property1;
...
copy->_propertyN = self->_propertyN;
return copy;
}
การให้เหตุผลในที่นี้คืออ็อบเจ็กต์ที่คัดลอกผลลัพธ์ควรสะท้อนถึงสถานะของอ็อบเจ็กต์ดั้งเดิม "." ผู้ประกอบการสามารถแนะนำผลข้างเคียงเนื่องจากสิ่งนี้เรียก getters ซึ่งอาจมีตรรกะ