标签(空格分隔): OCTips
OC的内存管理使用了引用计数器,一个对象中的NSUInteger类型
变量。MRC下向对象发送消息retain
使引用计数器加1,release
使引用计数器减1。当引用计数器为0时,对象被释放。此时再使用对象调用方法就会导致崩溃。
MRC内存管理原则:谁retain
,谁release
。
assign
assign
一般用于基本数据类型的值;如果非基本类型使用点语法获取值会出现警告Property access result unused - getters should not be used for side effects
,此时要使用方法调用[ ]
。其作用域为对象赋值操作的代码块区域,类似于一个局部变量。
// 运行于MRC下
@interface ViewController ()
@property (nonatomic, assign) NSMutableArray *array;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 作用域在viewDidLoad方法中
self.array = [NSMutableArray array];
[self.array addObject:@2];
[self.array addObject:@3];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.array removeObject:@2]; // 程序崩溃,因为对象已被释放
}
// setter
@property (assign, nonatomic) NSArray *array;
- (void)setArray: (NSArray *)array {
_array = array; // 直接赋值给实例变量
}
retain strong
持有特性,使一个对象的引用计数器加一。retain
是MRC下的,strong
是ARC下的。
// MRC下的方法调用
@interface ViewController ()
@property (nonatomic, retain) NSMutableArray *array;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.array = [NSMutableArray array]; // 创建时retainCount +1
[self.array addObject:@2];
[self.array addObject:@3];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.array removeObject:@2];
// [self.array retain];// 要继续使用,就要调用retain方法保持retainCount大于0。此时为2
[self.array release]; // retainCount +1, retainCount为0,释放对象
[self.array addObject:@4]; // 再调用方法,程序崩溃。
}
// MRC的setter,ARC 系统自动完成
@property (strong, nonatomic) NSArray *array;
- (void)setArray: (NSArray *)array {
if (_array != array) {
[_array release]; // 释放旧值
_array = [array retain];// 将对象引用计数器加一,再赋值给实例变量
}
}
weak
MRC下,如果一个对象的retainCount
为0,对象会被释放。但他的引用还保留了被释放对象的地址,形成野指针。此时调用方法,编译不会报错,但运行时会崩溃。因此MRC下还需要手动赋值为nil
。
ARC下,weak
属性在retainCount
为0时,会自动被赋值为nil。减少了形成野指针的风险。
ARC下如果想要手动释放对象,直接将对象引用赋值为nil即可。
copy
存在一个对象和他的副本,当你希望修改其中一个,但对另一个对象不影响时,使用copy。作为属性关键字时一般用于NSString
和block
。
相关点:
深拷贝:源对象引用计数不变,生成一份新的对象(拥有新的内存)
浅拷贝:源对象引用计数加一,生成一份新的引用,指向源对象。
值类型
和引用类型
的使用。
注意:如果对一个可变类型属性使用了copy
,会使其变成不可变类型。此时调用可变类型下的方法会出现崩溃。
@property (nonatomic, copy) NSMutableArray *array;
self.array = [NSMutableArray array];
[self.array addObject:@1]; // 崩溃,因为self.array 运行时是NSArray类型,是不能进行增删改操作的。
atomic nonatomic
使用了atomic
的属性系统会自动增加同步锁的代码。这样在多线程开发时,避免多个线程同时对属性进行写操作,造成无法预料的属性值。但是会增加性能消耗,同时也不能保证绝对的线程安全。另外,属性默认是atomic
的。
当然使用nonatomic
则能节省性能。
个人建议就忘掉atomic
吧,声明属性都使用nonatomic
。多线程安全读写的问题,就在需要写操作时使用NSLock
、@syncronized
等高级方式。
网友评论