属性语义copy和strong的理解

结论
一.如何区分[obj copy]是深拷贝还是浅拷贝?
1.当不可变类型对象调用copy拷贝后,不会产生新的对象,属于浅拷贝;
2.其他类型对象调用copy,都会产生新的不可变对象,属于深拷贝(遵循NSCopy协议并重写copyWithZone方法);
3.无论什么类型的对象,调用mutableCopy方法后, 都会产生新的可变对象, 但这不是属性特质的东西.

深浅拷贝完整的有demo的解析:http://blog.csdn.net/Mazy_ma/article/details/51899397


二.如何重写strong, copy属性的set方法
以dog.h文件的name属性为例:

ARC环境里
1.如果是strong, 则直接赋值

- (void)setName:(NSString *)name {
    _name = name
}

2.如果是copy, 则执行copy操作

- (void)setName:(NSString *)name {
     _name = [name copy];//系统会自动判断并执行"深或浅拷贝"
}


MRC环境下
I.如果是strong(即retain), 则

- (void)setName:(NSString *)name {
    if (_name != name) {
        [_name release];
        _name = [name retain];//引用计数+1
    }
}

II.如果是copy, 则

- (void)setName:(NSString *)name {
    if (_name != name) {
        [_name release];
        _name = [name copy];//系统自动判断"深或浅"拷贝
    }
}
//有人说,为什么都需要做if判断? 
//解析:因为如果_name和name指针指向的是同一个对象时,
//先执行的release操作可能导致"对象"引用计数为0,程序崩溃.



我的Demo代码:
ARC下
Dog.h文件

#import 

@interface Dog : NSObject

@property (nonatomic, strong) NSString *strongName;
@property (nonatomic, copy) NSString *cobyName;

//Dog.m无须实现
@end

控制器代码

#import "ViewController.h"
#import "Dog.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

#pragma mark - 当原对象是"固定对象"=不可变对象(此时的copy与strong是一样的,都是浅拷贝)
    NSString *oldStr = @"qpj";

    Dog *dd = [[Dog alloc]init];
    dd.strongName = oldStr;
    NSLog(@"strongName1:%@", dd.strongName);//qpj
    //修改oldStr
    oldStr = @"123";
    NSLog(@"strongName2:%@", dd.strongName);//qpj
    //思考:为什么还是输出qpj? 是苹果的错误?
    //答: oldStr指向了另一个对象了, 并没有修改原对象@"qpj", 所以输出的是qpj
    //所以,对于cobyName,同上!
    //结论:没有讨论的必要,因为所有对象本质都是不可变的!




#pragma mark - 当原对象是可变类型的(网络数据/DB数据)
    // 定义一个可变的字符,作为小狗的name
    NSMutableString *oo = [@"dakongyi" mutableCopy];

    Dog *dog = [[Dog alloc] init];
    dog.strongName = oo;
    dog.cobyName = oo;

    // 当小狗的name值发生改变时
    [oo appendString:@"HH"];   // oo ==> "dakongyiHH"
    //
    NSLog(@"原对象可变时-strong属性:%@",dog.strongName);// 打印结果:dakongyiHH
    //
    NSLog(@"原对象可变时-copy属性:%@",dog.cobyName);// 打印结果:dakongyi
    //结论:strong是浅拷贝; copy在此处是深拷贝

拓展:请写出copy和strong的set方法:
    //分析:这时候,应该需要区分原对象是否'可变'!
    //对于strong, 不管是否原对象可变,都是直接赋值_name=name, 
    //对于copy,   如果原对象不可变, 应该执行浅拷贝, 如果对象可变,应该执行深拷贝,即总结
    //_name = [name copy];//系统自己判断深浅拷贝copy
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end

你可能感兴趣的:(Objective-C,iOS基础-笔记)