**对象的属性
对象的属性封装了对象的所有值
所有的对象为了执行特定任务都需要记录信息,
1、许多对象被设计是为了模仿一个或者多个值,比如NSNumber类把数值型数据转换成啦数值对象;XYZPerson类模仿人拥有firstName和lastName;
2、有些对象在关系记录上应用较多,假定一个对象关联用户界面和界面所展示的信息,甚至对象需要记录用户界面元素和与界面关联的信息;
**申明暴露在外面的公共数据属性
1、不希望用户通过set方法修改属性
@property (readonly) NSString *fullName;
**通过对象的所有权管理对象的生命周期
1、copy 跟MRC一样
+ 在ARC中,系统不会自动加入copy,申请所有权,需要手动添加
实例:
- (id)initWithSomeOriginalString:(NSString *)aString {
self = [super init];
if (self) {
// 如不添加copy,系统自动添加strong,一旦外部string指向的对象改变,_instanceVariableForCopyProperty指向的对象也将改变
_instanceVariableForCopyProperty = [aString copy];
}
return self;
}
+copy基础
/*
copy
官方解释:
The copy attribute means that the property will use a strong reference, because it must hold on to the new object it creates.
如果之前习惯使用MMC的伙伴,那么在使用arc之后,对于NSString对象,仍然用copy申请所有权,
虽然arc可以使用strong,但使用strong,对象值改变,所有指针的值,都会改变
*/
//当first引用 strong 索取所有权时
self.badageView = [[XYZBadageView alloc] init];
NSMutableString *nameString31 = [NSMutableString stringWithString:@"John"];
NSLog(@"self.badageView%@,nameString%@",self.badageView.firstName,nameString);
self.badageView.firstName = nameString31;
[nameString31 appendString:@"ny"];
NSLog(@"self.badageView%@,nameString%@",self.badageView.firstName,nameString);
// 2014-02-21 16:27:26.345 ARCTest[4394:a0b] self.badageView(null),nameStringJohn
// 2014-02-21 16:27:26.346 ARCTest[4394:a0b] self.badageViewJohnny,nameStringJohnny
//当first引用 copy 索取所有权时
self.badageView = [[XYZBadageView alloc] init];
NSMutableString *nameString32 = [NSMutableString stringWithString:@"John"];
NSLog(@"self.badageView%@,nameString%@",self.badageView.firstName,nameString);
self.badageView.firstName = nameString32;
[nameString32 appendString:@"ny"];
NSLog(@"self.badageView%@,nameString%@",self.badageView.firstName,nameString);
// 2014-02-21 16:55:18.197 ARCTest[4606:a0b] self.badageView(null),nameStringJohnny
// 2014-02-21 16:55:19.659 ARCTest[4606:a0b] self.badageViewJohn,nameStringJohnny
note :block使用copy申请所有权
2、strong
strong同之前retain,增加引用计数;
需要注意一下几点
/*
加号方法创建的对象释放不及时
*/
self.lastModificationDate = [[NSDate alloc] initWithTimeIntervalSince1970:200];
NSDate *__weak originalDate11 = self.lastModificationDate;
self.lastModificationDate = [NSDate date];
NSLog(@"Last modification date changed from %@ to %@",
originalDate11, self.lastModificationDate);
// Last modification date changed from (null) to 2014-02-21 08:46:58 +0000
self.lastModificationDate = [NSDate dateWithTimeIntervalSince1970:200];
NSDate *__weak originalDate12 = self.lastModificationDate;
self.lastModificationDate = [NSDate date];
NSLog(@"Last modification date changed from %@ to %@",
originalDate12, self.lastModificationDate);
// Last modification date changed from 1970-01-01 00:03:20 +0000 to 2014-02-21 08:47:08 +0000
/*
强引用会因为对象的改变而改变,不会因为之前指针的转变而转变
*/
self.lastModificationDate = [[NSDate alloc] initWithTimeIntervalSince1970:200];
NSDate *originalDate = self.lastModificationDate;
self.lastModificationDate = [NSDate date];
NSLog(@"Last modification date changed from %@ to %@",
originalDate, self.lastModificationDate);
// Last modification date changed from 1970-01-01 00:03:20 +0000 to 2014-02-21 08:43:58 +0000
self.badageView = [[XYZBadageView alloc] init];
NSMutableString *nameString = [NSMutableString stringWithString:@"John"];
NSLog(@"self.badageView%@,nameString%@",self.badageView.firstName,nameString);
self.badageView.firstName = nameString;
[nameString appendString:@"ny"];
NSLog(@"self.badageView%@,nameString%@",self.badageView.firstName,nameString);
+ 循环引用
循环引用示意图
避免循环引用示意图
+
见下表:
@property (weak) id delegate;
@property (weak) id delegate;
note:weak的反义词是strong,此处没有必要特意申明,因为他是默认的
+
本地变量、成员变量默认申请强引用所有权(不在是autorelease)
self.lastModificationDate = [[NSDate alloc] initWithTimeIntervalSince1970:200];
NSDate *originalDate = self.lastModificationDate;
self.lastModificationDate = [NSDate date];
NSLog(@"Last modification date changed from %@ to %@",
originalDate, self.lastModificationDate);
//Last modification date changed from 1970-01-01 00:03:20 +0000 to 2014-02-21 10:15:50 +0000
Note:变量的强引用范围仅限于所在的方法作用域内,除非他指向啦其他的对象,或者被置空啦
如果你不想强引用本地变量的话,使用__weak:
NSObject * __weak weakVariable;
因为weak不申请对象的所有权,对象正在使用的时候被销毁是可以的。要避免这种危险的操作,当对象被释放之后,弱引用指针将会自动置空
self.lastModificationDate = [[NSDate alloc] initWithTimeIntervalSince1970:200];
NSDate *__weak originalDate = self.lastModificationDate;
self.lastModificationDate = [NSDate date];
NSLog(@"Last modification date changed from %@ to %@",
originalDate, self.lastModificationDate);
//2014-02-21 18:31:44.837 ARCTest[4875:a0b] Last modification date changed from (null) to 2014-02-21 10:31:44 +0000
originalDate变量很有可能被置空,当self.lastModificationDate 指针的指向改变,他对之前对象的强引用将消失,如果对象没有其他的对象指向他,对象将会被销毁,originalDate 将被置空
弱引用是令人很烦恼的,尤其下面这样:
NSObject * __weak someObject = [[NSObject alloc] init];
+ 下面这种写法是不安全的在上述代码中,新创建的对象没有被强引用,所以对象将会立即销毁,someObject指针将被置空
if (self.someWeakProperty) {
[someObject doSomethingImportantWith:self.someWeakProperty];
[someObject doSomethingImportantWith:self.someWeakProperty];
}
因为在多线程应用中,someWeakProperty指向的对象可能会被释放,if判断做得安全监测是无效的,你可以采用下面的方法(这个不太理解,在多线程中,下面的方法,同样不安全~~~)
NSObject *cachedObject = self.someWeakProperty; // 1
if (cachedObject) { // 2
[someObject doSomethingImportantWith:cachedObject]; //
[someObject doSomethingImportantWith:cachedObject]; // 3
} // 4
cachedObject = nil;
Use Unsafe Unretained References for Some Classes
在
Cocoa and Cocoa Touch 框架中,有些类是不支持弱引用的;比如: NSTextView、NSFont、NSColorSpace;
上述类中,如果你想引用中任意一个类,需使用theunsafe_unretained;
@property (unsafe_unretained) NSObject *unsafeProperty;
NSObject * NSObject * __unsafe_unretained unsafeReference;
unsaft引用和weak都有不保留对象所有权的性质,但是如果对象释放啦,他不会把对象置空
本文翻译来源:
代码实践,分线程要加自动释放池。队列的子类main方法,添加自动释放池,防止内存泄露