先來看一段代碼
NSMutableArray *arr1 = [[NSMutableArray alloc] initWithObjects:@1, @2, @3, nil];
NSMutableArray *arr2 = arr1;
[arr1 removeObjectAtIndex:0];
在刪除arr1
第一個元素的同時,arr2
的第一個元素也被刪除了,這很好理解,因為兩個對象都指向同一個地址
如果想操作arr1
的同時不影響到arr2
,則只需改動一句
NSMutableArray *arr2 = [arr1 copy];
如果調用copy
方法的對象是自己定義的對象,那么該對象需要實現NSCopying
協議
Person.h
@interface Person : NSObject<NSCoding, NSCopying>
@property(nonatomic, copy) NSString *name;
@property(nonatomic, assign) NSInteger age;
@end
Person.m
- (id)copyWithZone:(NSZone *)zone
{
Person *copy = [[[self class] alloc] init];
copy.name = self.name;
copy.age = self.age;
return copy;
}
更復雜的情況
@interface Book : NSObject
@property(nonatomic, copy) NSString *name;
@property(nonatomic, assign) float price;
@end
@interface Person : NSObject<NSCopying>
@property(nonatomic, copy) NSMutableString *name;
@property(nonatomic, strong) Book *book;
@end
@implementation Person
- (id)copyWithZone:(NSZone *)zone
{
Person *copy = [[[self class] alloc] init];
copy.name = self.name;
copy.book = self.book;
return copy;
}
調用
Book *book = [Book new];
book.name = @"OBJC";
book.price = 89.99;
Person *p1 = [Person new];
p1.name = [NSMutableString stringWithString:@"JC"];
p1.book = book;
Person *p2 = [p1 copy];
[p2.name appendString:@"Henry"];//這里會報錯(unrecognized selector)
p2.book.name = @"JAVA";
p2.book.price = 79.99;
這里需要重點注意下,程序中p2.name
明明定義的是NSMutableString
類型,為什么會報不存在方法的錯誤呢?因為在合成getter
和setter
方法的時候沒有提供mutableCopy
指示符,因此即使定義實例變量時使用了可變類型
,但只要使用copy
指示符,實例變量實際得到的值總是不可變對象
,系統默認的setter
方法如下
- (void)setName:(NSMutableString *)name
{
_name = [name copy];
}
因此需要在person.m
文件中添加如下代碼
- (void)setName:(NSMutableString *)name
{
_name = [name mutableCopy];
}
p2.book
任意屬性變化也會影響到p1.book
的屬性
這里需要修改兩個地方
- 讓
Book
類實現NSCopying
協議 - 在
Person.m
的- (id)copyWithZone:(NSZone *)zone
方法中將copy.book = self.book;
替換成copy.book = [self.book copy];