copy 自定義對象

要向讓咱們本身建立的對象調用copy 方法,( [p copy] ) 前提條件是:程序員

1>  遵照NSCopying協議  (本質上就是方便程序員編寫代碼時候,有快捷提示) 
2> 實現 - (id)copyWithZone:(NSZone *)zone數組

     copy方法,      最終都會調用copyWithZone方法atom

mutablecopy方法,最終都會調用mutableCopyWithZone方法spa

 

有一個模型對象Personcode

@interface Person : NSObject<NSCopying,NSMutableCopying>

@property(nonatomic,copy)NSString *name;
@property(nonatomic,assign)NSInteger age;

@end

 

遵照NSCopying協議 ,重寫Person 的 copyWithZone方法 和 mutableCopyWithZone     copy操做一個對象,複製給一個新的對象。對象

- (id)copyWithZone:(NSZone *)zone
{
    // 1> 實例化對象,self 是對象
    // self.class可以保證繼承的子類一樣使用copy方法
    Person *p = [[self.class alloc] init];
    //Person * p = [[self.class allocWithZone:zone] init];

    // 2> 給屬性賦值,深拷貝一份屬性[self.name copy]字符串的copy方法,賦給新對象,可是這裏不須要由於屬性是不可變字符串。
    p.name = self.name;
    p.age = self.age;

    // 3> 返回新對象
    return p;
}

 

驗證: 繼承

- (void)viewDidLoad {
    [super viewDidLoad];


    Person *p = [Person new];

    Person *p2 = [p copy];

    
    NSLog(@"%@,%@", p, p2);

}

 結果以下:兩個對象地址不同。哦了字符串

 

 

 

上面的模型屬性中不包含容器類對象,若是包含容器類對象,咱們這樣寫的話,會致使容器自己是深拷貝了,可是容器裏面盛放的對象並非深拷貝。裏面的對象依舊是淺拷貝。面對這種狀況應該這樣寫:it

有一個Person模型對象,其中有一個 NSArray屬性 table

@interface Person : NSObject<NSCopying,NSMutableCopying>

@property(nonatomic,copy)NSString *name;
@property(nonatomic,assign)NSInteger age;
@property(nonatomic,strong)NSArray *arr;

@end

重寫 Person 的 copyWithZone方法 和 mutableCopyWithZone 注意:p.arr = 不能簡單的賦值,須要調用initWithArray:  copyItems: 方法,這個方法可讓數組實現深拷貝,可是僅限於數組中沒有再嵌套容器類,若是數組中再嵌套容器類,這個方法就不行了,須要使用歸檔。

- (id)copyWithZone:(NSZone *)zone{
    
    //實例化對象
    //self.class可以保證繼承的子類能夠使用copy方法
    Person * p = [[self.class alloc] init];
    
    //給屬性賦值
    p.age = self.age;
    p.name = self.name;

//這裏要注意了,不能單純的賦值,單純的賦值,就是表明引用同一個數組,當一個數組中的元素改變了。copy的數組中也會改,因此要深copy一份數組
    p.arr = [[NSArray alloc] initWithArray:self.arr copyItems:YES];
    
    //返回新對象
    return p;
    
}

 

另外須要注意:initWithArray: copyItem: 這個方法調用時,self.arr中的對象 必需要具備copy的能力,否則會崩潰的,因此咱們要將數組中的元素實現copy的方法。

- (id)copyWithZone:(NSZone *)zone{
    
    //實例化對象
    //self.class可以保證繼承的子類能夠使用copy方法
    pm * p = [[self.class alloc] init];
    
    //給屬性賦值
    p.days = self.days;
    
    //返回新對象
    return p;
    
}


- (id)mutableCopyWithZone:(NSZone *)zone{
    
    //實例化對象
    //self.class可以保證繼承的子類能夠使用copy方法
    pm * p = [[self.class alloc] init];
    
    //給屬性賦值
    p.days = self.days;
    
    //返回新對象
    return p;
    
}

 

驗證:

//建立數組
    pm *pmm = [pm new];
    pmm.days = @"one";
    NSArray *array = [NSArray arrayWithObjects:pmm, nil];
    

    //建立模型
    Person *p = [Person new];
    //給模型中的數組賦值
    p.arr = array;
    
    
    
    //copy模型
    Person *p2 = [p copy];
    //修改copy後的模型數組中對象的值
    [[p2.arr lastObject] setDays:@"two"] ;
    
    //打印結果
    NSLog(@"%@", [[p.arr lastObject] days]);
    NSLog(@"%@", [[p2.arr lastObject] days]);

結果以下:修改copy後的對象中的數組屬性中的元素後, 原始的對象中的值並無變,說明copy成功了。

相關文章
相關標籤/搜索