几个iOS的属性关键字
1.nonatomic、atomiac:
nonatomic:非原子的, atomiac 原子的 。属性默认是 atomiac , 也就是原子性的。nonatomic执行效率高。
atomiac:读写安全,但效率低,不是绝对的安全。
2.readwrite、readonly:
readwrite 读写,readonly 只读。 属性默认是 readwrite , 支持读写。
readwirte: 属性同时具有 set 和 get 方法。
readonly: 属性只具有 get 方法。
3.assign:
既可以修饰基本数据类型,也可以修饰对象类型; setter 方法的实现是直接赋值,一般用于基本数据类型 ;修饰基本数据类型,如 NSInteger、BOOL、int、float 等;修饰对象类型时,不增加其引用计数;会产生悬垂指针(悬垂指针:assign 修饰的对象在被释放之后,指针仍然指向原对象地址,该指针变为悬垂指针。这时候如果继续通过该指针访问原对象的话,就可能导致程序崩溃)。
strong
strong 是对象的默认属性关键字,此特质表明该属性定义了一种“持有关系”,为这种属性设置新值时,设置方法既会先保留新值,并释放旧值,然后再将新值设置上去。此时与原对象指向的是同一地址。当原对象为可变对象时,将原对象赋给strong修饰的不可变对象,修改原对象,那我们不可变的对象也会随之改变
copy
此特质所表达的所属关系与strong类似,然后设置方法并不保留(retain)新值,而是将其复制(copy)。copy修饰不可变对象,strong修饰可变对象。
- copy修饰不可变对象、原对象为不可变对象时,将原对象赋值给属性,会将原对象进行copy,此时是浅复制,两个指针指向的是同一个地址。
- copy修饰不可变对象,原对象为可变对象时,将原对象赋值给属性,会将原对象进行copy,此时是深复制,两个对象指向的不同的地址,属性所指的是可变对象的副本,原对象如果被修改的话,不会影响属性的值。
- copy修饰可变对象,如果原对象是不可变对象并赋值给属性,那么进行的是浅复制,指向同一地址。
- copy修饰可变对象,如果原对象是可变对象并赋值给属性,此时进行的是深复制,属性指向的是原对象的不可变副本,即此时属性为不可变对象,这时对属性进行增删改的操作,就会因为找不到方法而报错。
示例:
#import <Foundation/Foundation.h>
@interface test : NSObject
@property (nonatomic, copy) NSString *stringCopy;
@property (nonatomic, strong) NSString *stringStrong;
@property (nonatomic, copy) NSMutableString *mutableStringCopy;
@end
// main.m
int main(int argc, const char * argv[]) {
@autoreleasepool {
test * test1 = [[test alloc] init];
NSString *string = @"222";
test1.stringCopy = string;
test1.stringStrong = string;
NSLog(@"%p %p %p", string, test1.stringCopy, test1.stringStrong);
NSMutableString *string2 = [[NSMutableString alloc] initWithString:@"111"];
test1.stringCopy = string2;
test1.stringStrong = string2;
NSLog(@"%p %p %p", string2, test1.stringCopy, test1.stringStrong);
[string2 appendString:string];
NSLog(@"%@ %@ %@", string2, test1.stringCopy, test1.stringStrong);
}
return 0;
}
通过程序来实际看一下到底有什么区别。
输出结果:
0x100004008 0x100004008 0x100004008
0x1005229a0 0x84e16ab6357c8f7c 0x1005229a0
111222 111 111222
在赋值类型为NSMutableString时,因为对NSMutableString 执行copy方法是深拷贝 ,开辟了新的内存,所以copy修饰的属性内存地址变了,而strong只是引用计数+1,内存地址还是源字符串的,所以改变影响不到copy修饰的属性,而会改变strong修饰的属性。当源字符串是不可变类型时,copy、strong改变源字符串,效果一样;当源字符串是可变类型时,copy 修饰的是深拷贝,改变源字符串,不影响copy的属性内容;strong修饰的属性,就随着源字符串的改变而变了。
对NSMutableString类型的变量使用copy,如:
@property (nonatomic, copy) NSMutableString *mutableStringCopy;
进行如下操作:
test1.mutableStringCopy = string2;
[test1.mutableStringCopy appendString:@"222"];
程序会崩溃,报错:
'-[NSTaggedPointerString appendString:]: unrecognized selector sent to instance 0xb04010f44c5ef9bd'
这是因为赋值时得到的对象是不可变对象,不可变对象肯定不会存在可变类型的方法。可以在我的另一篇博客中看一看有关内容:OC Foundation框架 对象复制。