美文网首页
IOS 属性修饰符 assign weak copy

IOS 属性修饰符 assign weak copy

作者: 李波小丑 | 来源:发表于2017-02-22 09:29 被阅读0次

    assign

    弱引用
    适用于基本数据类型 int float double bool

    weak

    弱引用
    适用于 NSObject 对象,weak修饰的对象在释放之后,指针地址会被置为nil。
    runtime 对注册的类会进行布局,对于weak对象会放入一个hash表中。用weak指向的对象内存地址作为key,当此对象的引用计数器为0时会dealloc,加入weak指向的对象内存地址是a,那么就会以a为键,在这个weak表中搜索,找到所有以a为键的weak对象,并设置为nil

    copy

    为什么 NSString NSArray NSDictionary 经常使用copy?
    使用copy的目的是为了让对象的属性不受外界的影响。假如传入的是NSMutableArray,使用copy后就变成了NSArray,外界不能改变。

    NSError 使用copy因为其实现了copying协议

    这样写有什么问题: @property (copy) NSMutableArray *array;

    1. 添加,删除数组内的元素会因为找不到对应的方法而崩溃,因为copy就是复制了一个不可变NSArray对象。
    2. 使用atomic 严重影响性能

    深拷贝 浅拷贝
    对系统非容器类不可变对象调用copy方法其实只是把当前对象的指针指向了原对象的地址,而调用mutableCopy方法则是新分配了一块内存区域并把新对象的指针指向了这块区域。
    对于可变对象来说,调用copy和mutableCopy方法都会重新分配一块内存,但对可变对象调用copy方法会返回不可变对象。
    但重新改变浅复制对象的值,会变成深拷贝

    NSString *str = @"123";
    NSString *strCopy = [str copy]; // 浅拷贝
        
    NSLog(@"str = %@    strCopy = %@",str,strCopy);
    NSLog(@"str地址:%p    strCopy地址:%p",str,strCopy);
    str = @"a"; // 改变值会真正的实现拷贝(深拷贝)
    NSLog(@"str = %@    strCopy = %@",str,strCopy);
    NSLog(@"str地址:%p    strCopy地址:%p",str,strCopy);
        
    NSMutableString *mustr = [str copy]; // mustr 已是不可变对象
    NSMutableString *muCopy = [str mutableCopy];
    NSLog(@"mustr = %@    muCopy = %@",mustr,muCopy);
    NSLog(@"mustr地址:%p     muCopy地址:%p",mustr,muCopy);
    [muCopy appendString:@"b"];
    NSLog(@"mustr = %@    muCopy = %@",mustr,muCopy);
    NSLog(@"mustr地址:%p     muCopy地址:%p",mustr,muCopy);
    
    
    str = 123    strCopy = 123
    str地址:0x106ecdc58    strCopy地址:0x106ecdc58
    str = a    strCopy = 123
    str地址:0x106ecdcb8    strCopy地址:0x106ecdc58
    mustr = a    muCopy = a
    mustr地址:0x106ecdcb8     muCopy地址:0x60000007cc80
    mustr = a    muCopy = ab
    mustr地址:0x106ecdcb8     muCopy地址:0x60000007cc80
    

    对于不可变容器对象调用copy方法只是增加了对原对象的指针的引用,调用mutableCopy方法是重新分配一块内存,然后把新对象指针指向新内存。
    而对于可变对象不管是调用copy还是mutableCopy都是新分配一块内存。但虽然重新分配了一块内存,但是对象里面的数据依然是指针赋值。

    NSArray *array = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"1"],@"2",@"3", nil];
        
    NSArray *arrayCopy = [array copy];
    NSArray *arrayMutableCopy = [array mutableCopy];
    NSLog(@"array地址:%p     arrayCopy地址:%p      arrayMutableCopy地址:%p",array,arrayCopy,arrayMutableCopy);
    NSLog(@"array = %@   arrayCopy = %@    arrayMutableCopy = %@",array,arrayCopy,arrayMutableCopy);
        
    NSMutableArray *mutableArrayCopy = [array copy];
    NSMutableArray *mutableArrayMutableCopy = [array mutableCopy];
    NSLog(@"array地址:%p   mutableArrayCopy地址:%p    mutableArrayMutableCopy地址:%p",array,mutableArrayCopy,mutableArrayMutableCopy);
    NSLog(@"array = %@   mutableArrayCopy =  %@    mutableArrayCopy =  %@",array,mutableArrayCopy,mutableArrayMutableCopy);
        
    NSMutableString *mustr = array[0];
    [mustr appendString:@"2"];
    NSLog(@"array地址%p     arrayCopy地址%p      arrayMutableCopy地址%p     mutableArrayCopy地址%p    mutableArrayCopy地址%p",array,arrayCopy,arrayMutableCopy,mutableArrayCopy,mutableArrayMutableCopy);
    NSLog(@"array = %@   arrayCopy = %@    arrayMutableCopy = %@   mutableArrayCopy =  %@    mutableArrayCopy =  %@",array,arrayCopy,arrayMutableCopy,mutableArrayCopy,mutableArrayMutableCopy);
    
    
    array地址:0x6080000538f0     arrayCopy地址:0x6080000538f0      arrayMutableCopy地址:0x608000050d70
    array = (
        1,
        2,
        3
    )   
    arrayCopy = (
        1,
        2,
        3
    )    
    arrayMutableCopy = (
        1,
        2,
        3
    )
    array地址:0x6080000538f0   mutableArrayCopy地址:0x6080000538f0    mutableArrayMutableCopy地址:0x608000050890
    array = (
        1,
        2,
        3
    )   
    mutableArrayCopy =  (
        1,
        2,
        3
    )    
    mutableArrayCopy =  (
        1,
        2,
        3
    )
    array地址0x6080000538f0     arrayCopy地址0x6080000538f0      arrayMutableCopy地址0x608000050d70     mutableArrayCopy地址0x6080000538f0    mutableArrayCopy地址0x608000050890
    array = (
        12,
        2,
        3
    )   
    arrayCopy = (
        12,
        2,
        3
    )    
    arrayMutableCopy = (
        12,
        2,
        3
    )   
    mutableArrayCopy =  (
        12,
        2,
        3
    )    
    mutableArrayCopy =  (
        12,
        2,
        3
    )
    

    可以看到当更改原数组的值之后,所有新数组的值都更改了,即使调用了MutableCopy方法创建的新数组里面的值也因此更改,所以可以看出对于系统容器类对象,其元素对象始终是指针复制。

    自己定义的类默认没有实现NSCopying协议

    Person *p1 = [[Person alloc] init];
    Person *p2 = [p1 copy]; //崩溃
    
    *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Person copyWithZone:]: unrecognized selector sent to instance 0x608000011570'
    

    property

    @property = ivar(实例变量) + getter + setter

    @implementation Book
    @dynamic  name;
    @synthesize age = _age;
    

    @synthesize
    编译器自动生成 getter/setter 方法
    当有自定义的存取方法时,不会自动生成。

    @dynamic
    告诉编译器不自动生成 getter/setter 方法

    在protocol中使用@property只会生成setter getter方法,目的是希望遵守协议的对象能实现该属性方法
    当同时重写了setter和getter时,系统就不会生成ivar。解决方法有下面两种

    @interface ViewController () {
        // NSString *_name; 方法1:手动创建ivar
    }
    @property (nonatomic, strong) NSString *name;
    @end
    
    @implementation ViewController
    //@synthesize name = _name; 方法2:使用@sysnthesize关联@property 与ivar
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    }
    
    - (NSString *)name{
        //return _name;
    }
    
    - (void)setName:(NSString *)name{
        //_name = @"";
    }
    
    @end
    

    set get

    - (void)setName:(NSString *)name{
        if (_name != name) {
            [name retain];
            [_name release];
            _name = name;
        }
    }
    
    self.name = @"dog"; // 调用 setter
    NSLog(@"%@",self.name); // 调用 getter
    
    _name = @"cat"; // 什么都不调用
    NSLog(@"%@",_name); // 什么都不调用
    

    相关文章

      网友评论

          本文标题:IOS 属性修饰符 assign weak copy

          本文链接:https://www.haomeiwen.com/subject/fcvpwttx.html