標籤:
copy文法的目的:改變副本的時候,不會影響到來源物件;
深拷貝:內容拷貝,會產生新的對象。新對象計數器置為1,來源物件計數器不變。
淺拷貝:指標拷貝,不會產生新的對象。來源物件計數器+1。
拷貝有下面兩個方法實現拷貝:
- (id)copy; - (id)mutableCopy;
對象要實現copy,必須實現<NSCopying>協議
數組,字典,字串都已經實現了<NSCopying>協議,以下以字串為例:
1.不可變字串調用copy實現拷(淺拷貝)
NSString *string = [[NSString alloc] initWithFormat:@"abcde"]; // copy產生的是不可變副本,由於來源物件本身就不可變,所以為了效能著想,copy會直接返回來源物件本身 // 來源物件計數器會+1 // 在淺拷貝情況下,copy其實就相當於retain NSString *str = [string copy];
2.不可變字串調用mutableCopy實現拷貝,(深拷貝)
NSString *string = [[NSString alloc] initWithFormat:@"abcd"]; // 產生了一個新的對象,計數器為1。來源物件的計數器不變。 NSMutableString *str = [string mutableCopy];//此時存在兩個對象// str:1和// string:1 // str和string不是相同對象 // NSLog(@"%i", str == string);//0 [str appendString:@" abcd"];//修改str不影響string NSLog(@"string:%@", string); NSLog(@"str:%@", str);
3.可變字串調用copy實現拷貝(深拷貝)
NSMutableString *string = [NSMutableString stringWithFormat:@"age is %i", 10]; // 會產生一個新對象,str計數器為1 NSString *str = [string copy];
4.可變字串的MutableCopy(深拷貝)
NSMutableString *string = [NSMutableString stringWithFormat:@"age is %i", 10]; // 會產生一個新對象,str計數器為1 NSMutableString *str = [string mutableCopy]; [str appendString:@"1234"];//修改新對象不影響原對象 NSLog(@"str:%@", str); NSLog(@"string:%@", string);
5.拷貝自訂對象,下面以Student對象為例
a.Student要實現copy,必須實現<NSCopying>協議
b.實現<NSCopying>協議的方法:
- (id)copyWithZone:(NSZone *)zone
Student.h檔案
@interface Student : NSObject <NSCopying> // copy代表set方法會release舊對象、copy新對象 // 修改外面的變數,並不會影響到內部的成員變數 // 建議:NSString一般用copy策略,其他對象一般用retain @property (nonatomic, copy) NSString *name; + (id)studentWithName:(NSString *)name; @end
Student.m檔案
#import "Student.h" @implementation Student + (id)studentWithName:(NSString *)name { // 這裡最好寫[self class] Student *stu = [[[[self class] alloc] init] autorelease]; stu.name = name; return stu; } - (void)dealloc { [_name release]; [super dealloc]; } #pragma mark description方法內部不能列印self,不然會造成死迴圈 - (NSString *)description { return [NSString stringWithFormat:@"[name=%@]", _name]; } #pragma mark copying協議的方法 // 這裡建立的副本對象不要求釋放 - (id)copyWithZone:(NSZone *)zone { Student *copy = [[[self class] allocWithZone:zone] init]; // 拷貝名字給副本對象 copy.name = self.name; return copy; } @end
拷貝Student
Student *stu1 = [Student studentWithName:@"stu1"]; Student *stu2 = [stu1 copy]; stu2.name = @"stu2"; NSLog(@"stu1:%@", stu1); NSLog(@"stu2:%@", stu2); [stu2 release];
小結:
建議:NSString一般用copy策略,其他對象一般用retain;
只有一種情況是淺拷貝:不可變對象調用copy方法時,其他情況都為深拷貝;
iOS 深拷貝、淺拷貝、自訂對象拷貝簡介