默认的情况下。property = Ivar + getter + setter
get set只能重写一个。重写两个要@synthesize nameString = _nameString;
MRC下重写set
-(void)setName:(NSString *)name
{
if (_name != name)
{
[_name release];
[name retain];
_name = name;
}
}
property属性:
1.readonly
如果您不希望通过setter方法更改属性,您可以向属性声明中添加一个属性来指定它应该是只读的。在这种情况下。readonly告诉编译器只生成getter方法。不会生成setter方法。但是可以用KVC和Ivar进行赋值操作。
属性默认是readwrite
- atomic
属性默认为atomic。atomic比较慢。
即使从不同线程同时调用访问器,合成的访问器也要确保值总是由getter方法完全检索或通过setter方法完全设置。(说人话。可以得到完整的value和完整的set value)
因为原子访问器方法的内部实现和同步是私有的,所以不可能将合成的访问器与您自己实现的访问器方法组合在一起。例如,如果您尝试为原子的readwrite属性提供自定义setter,但让编译器合成getter,那么您将得到编译器警告。 - nonatomic
您可以使用非原子属性属性来指定合成的访问器直接设置或返回一个值,而不必保证从不同线程同时访问相同的值会发生什么。因此,访问非原子属性要比访问原子属性快得多,并且可以将合成的setter和自己的getter实现结合起来:
4.weak & strong
__weak TestObj * weakObj = [NSObject new];
block = ^(){
__strong TestObj *strongObj = weakObj;
if(! strongObj) return;
NSLog(@"TestObj对象地址:%@",strongObj);
dispatch_async(dispatch_queue_create(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^{
for (int i = 0; i < 1000000; i++) {
// 模拟一个耗时的任务
}
NSLog(@"耗时的任务 结束 TestObj对象地址:%@",strongObj);
});
关于weak的实现。https://github.com/BiBoyang/Study/wiki/@property的研究(二)-weak关键字.
5.copy
但是NSMutableString用strong修饰。
@interface XYZBadgeView : NSView
@property NSString *firstName;
@property NSString *lastName;
@end
NSMutableString *nameString = [NSMutableString stringWithString:@"John"];
self.badgeView.firstName = nameString;
[nameString appendString:@"ny"];
- unsafe_unretained
ARC下用__unsafe_unretained 替代__weak
有些不能被weak修饰的类比如:
NSATSTypesetter
,NSColorSpace
,NSFont
,NSMenuView
,NSParagraphStyle
,NSSimpleHorizontalTypesetter
, andNSTextView
.
使用alloc创建对象;Runtime负责释放对象
您不能显式调用dealloc,或实现或调用retain、release、retainCount或autorelease。
如果需要管理实例变量以外的资源,可以实现dealloc方法。您不必(实际上您不能)释放实例变量,但是您可能需要调用[systemClassInstance setDelegate:nil]上的系统类和其他没有使用ARC编译的代码。
ARC中的自定义dealloc方法不需要调用[super dealloc]
不能为访问器提供以new开头的名称。这又意味着,例如,除非指定了不同的getter,否则不能声明名称以new开头的属性:
// Won't work:
@property NSString *newTitle;
// Works:
@property (getter=theNewTitle) NSString *newTitle;
__strong是默认值。只要有一个指向对象的强指针,对象就保持“活着”。
__weak指定了一个引用,它不能保持被引用对象的生命。当对象没有强引用时,弱引用被设置为nil。
__unsafe_unretain指定一个引用,该引用不保存被引用的对象,当对象没有强引用时不设为nil。如果它引用的对象被释放,指针就会保持悬空状态。
__autoreleasing用于表示通过引用(id *)传递的参数,并在返回时自动递增。
两种block解决循环引用的方式。
MyViewController *myController = [[MyViewController alloc] init…];
// ...
MyViewController * __weak weakMyViewController = myController;
myController.completionHandler = ^(NSInteger result) {
[weakMyViewController dismissViewControllerAnimated:YES completion:nil];
};
MyViewController * __block myController = [[MyViewController alloc] init…];
// ...
myController.completionHandler = ^(NSInteger result) {
[myController dismissViewControllerAnimated:YES completion:nil];
myController = nil;
};
MyViewController *myController = [[MyViewController alloc] init…];
// ...
MyViewController * __weak weakMyController = myController;
myController.completionHandler = ^(NSInteger result) {
MyViewController *strongMyController = weakMyController;
if (strongMyController) {
// ...
[strongMyController dismissViewControllerAnimated:YES completion:nil];
// ...
}
else {
// Probably nothing...
}
};
__bridge_transfer或CFBridgingRelease将一个非Objective-C指针移动到Objective-C,并将所有权转移到ARC。
__autoreleasing
- (BOOL)save:(NSError **)error;
其实,这个(NSError **)error相当于(NSError * __autoreleasing *)error,编译器默认为其生成了__autoreleasing修饰符。
编译器默认生成__autoreleasing修饰符的做法,也是在贯彻内存管理原则,即确保只有通过以alloc/new/copy/mutableCopy开头的方法返回的对象才能被持有。
虽然当我们自己定义id *obj类型的参数时,也可以显式指定它的所有权修饰符为其他,并通过编译,但为了贯彻内存管理原则,还是应该将id *obj类型的参数的所有权修饰符指定为__autoreleasing。