iOS关键字(copy和strong)

属性的含义

属性的本质就是:实例变量 + get方法 + set方法。
众多属性关键字是对自动生成的get、set方法进行了修饰。

属性的功能

1.给现有的成员变量生成一对setter/getter方法。
2.如果没有声明成员变量,自动声明一个_属性名的私有变量(默认成员变量是受保护的)。

iOS的属性关键字

1.atomic和nonatomic:
指定合成的存取方式是否为原子操作(是否线程安全)

atomic合成的存取方法都是线程安全的,当一个线程进入存取方法体之后,其他线程无法进入该存取方法,这样就可以避免多线程破坏对象的数据完整性,但会造成性能下降。atomic是默认值。

nonatomic由于atomic的线程安全会造成性能下降,在大多数单线程环境,会考略使用nonatomic来提高存取方法的访问性能。

2. readwrite,readonly

readwrite:读写,默认属性为readwrite,属性同时具有set和get方法;

readonly:只读,属性只具有get方法。

3.assign

既可以修饰基本数据类型,也可以修饰对象类型。该指示符指定对属性只是进行简单赋值,不更改对所赋的值的引用计数。assign的对象回产生悬垂指针,当对象没有持有者被废弃时,assign修饰的对象指针还会指向原来的地址。访问悬垂指针,可能回导致程序崩溃。

这个指示符主要适用于NSInteger等基本类型,以及short、float、double、结构体等各种C数据类型。
引用计数是Objective-C内存回收的概念,当一个对象的引用计数大于0时,表明该对象还不应该被回收。由于NSInteger等基础类型,以及short.float、double、结构体等各种C数据类型都不存在内存回收的问题,因此使用assign即可。

4. copy:

如果使用copy指示符,那么当调用setter方法对成员变量赋值时,会将被赋值的对象复制一个副本,再将该副本赋值给成员变量。copy指示符会将原成员变量所引用对象的引用计数减1。当成员变量的类型是可变类型,或其子类是可变类型时,被赋值的对象有可能在赋值之后被修改,如果程序不需要这种修改影响 setter方法设置的成员变量的值,此时就可考虑使用copy指示符。

此特质所表达的所属关系与strong类似,然后设置方法并不保留(retain)新值,而是将其复制(copy)。copy修饰不可变对象,strong修饰可变对象。

copy修饰不可变对象、原对象为不可变对象时,将原对象赋值给属性,会将原对象进行copy,此时是浅复制,两个指针指向的是同一个地址。
copy修饰不可变对象,原对象为可变对象时,将原对象赋值给属性,会将原对象进行copy,此时是深复制,两个对象指向的不同的地址,属性所指的是可变对象的副本,原对象如果被修改的话,不会影响属性的值。
copy修饰可变对象,如果原对象是不可变对象并赋值给属性,那么进行的是浅复制,指向同一地址。
copy修饰可变对象,如果原对象是可变对象并赋值给属性,此时进行的是深复制,属性指向的是原对象的不可变副本,即此时属性为不可变对象,这时对属性进行增删改的操作,就会因为找不到方法而报错。

5.strong

是对象的默认属性关键字,表明该属性定义一种“持有关系”,为这种属性设置新值时,设置方法即会先保留新值,并释放旧值,然后再将新值设置上去。此时与原对象指向的同一地址。当原对象为可变对象时,将原对象赋给strong修饰的不可变对象,修改原对象,那我们不可变的对象也会随之改变。
6.week
弱应用,表示该属性是一种“非拥有关系”。为这种属性设置新值时既不会保留新值也不会释放旧值,类似于assgin。 然而在对象被摧毁时,属性也会被清空(置nil)。

strong和copy的深浅复制

想了解一下概念

深浅拷贝
1,深拷贝:内容拷贝,拷贝数据到一块新内存区域,指针指向拷贝的数据区域。(另外创建一个一摸一样的对象,新对象与原对象不共享内存,修改新对象不会改变原对象)。

2,浅拷贝:指针拷贝,复制一个新指针,指针指向同一块内存区域。实际内存并没有发生拷贝(只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存)。

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface test : NSObject
@property (nonatomic, copy) NSString* stringCopy;
@property (nonatomic, strong) NSString* stringStrong;
@property (nonatomic, copy) NSMutableString* mutableAStringCopy;
@end

NS_ASSUME_NONNULL_END
#import <Foundation/Foundation.h>
#import "test.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!");
        test* a = [[test alloc] init];
        NSString* string = @"222";
        a.stringCopy = string;
        a.stringStrong = string;
        NSLog(@"%p %p %p", string, a.stringCopy, a.stringStrong);
        
        NSMutableString* string2 =  [[NSMutableString alloc] initWithString:@"111"];
        a.stringCopy = string2;
        a.stringStrong = string2;
        NSLog(@"%p, %p, %p",string2, a.stringCopy, a.stringStrong);
        
        [string2 appendString:string];
        NSLog(@"%@, %@, %@",string2, a.stringCopy, a.stringStrong);
    }
    return 0;
}

运行结果
在这里插入图片描述

当赋值类型为NSMutableString时,对copy修饰的赋值时,
为深拷贝,新的赋值的地址发生改变,而strong修饰的赋值时,只是引用计数+1,内存地址还是原字符串。当赋值当赋值类型为NSString时,对copy修饰的赋值时,
为浅拷贝,新的赋值的地址没有发生改变,而strong修饰的赋值时,只是引用计数+1,内存地址还是原字符串。
当源字符串是不可变类型时,copy,strong修饰时改变原字符串,效果一样。当源字符串是可变类型,copy修饰的是深拷贝,改变原字符串,不影响copy的属性内容。strong修饰的是浅拷贝,改变原字符串,就会影响。

而进行如下操作时,

//  Item.h

#import <Foundation/Foundation.h>

@interface Item : NSObject
@property (nonatomic , copy) NSMutableString* name;
@end

//  main.m

#import "Item.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Item* item = [Item new];
        item.name = [NSMutableString stringWithString: @"111"];
        [item.name appendString:@"222"];
    }
    return 0;
}

此时就会运行错误

[NSTaggedPointerString appendString:]: unrecognized selector sent to instance 0x966d797a018becfe

提示不允许修改name属性值,这是因为程序定义name属性时使用的是copy指示符。也就是说,setName: 方法的代码如下:

-(void) setName: (NSMutableString*) aname {
	name = [aname copy];
}

定义合成getter、setter方法时没有提供mutableCopy指示符,因此,即使定义实例变量时使用了可变类型,但只要使用了copy指示符,实例变量实际得到的值总是不可变对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值