一、@property修饰符分为三类:
1、原子性:atomic(默认)/nonatomic
在多线程环境下,原子操作是必要的,否则有可能引起错误的结果。加了atomic,setter函数会变成下面这样:
{lock}
if (property != newValue) {
property = newValue;
}
{unlock}
nonatomic禁止多线程变量保护,提高性能。
atomic是Objc使用的一种线程保护技术,基本上来讲,是防止在写未完成的时候被另外一个线程读取,造成数据错误。而这种机制是耗费系统资源的,如果没有使用多线程间的通讯编程,那么应该使用nonatomic。
2、读写性:readonly/readwrite(默认),readonly只生成getter,readwrite生成getter和setter。
3、内存管理特性(ARC模式):
ARC 的规则非常简单:只要还有一个变量指向对象,对象就会保持在内存中。当指针指向新值,或者指针不再存在时,相关联的对象就会自动释放。这条规则对于实例变量、synthesize属性、局部变量都是适用的
3.1、strong:标识对对象的强引用,只要有一个以上强引用指向对象,对象就不会被释放。
3.2、weak:weak型的指针变量仍然可以指向一个对象,但不属于对象的拥有者,如果只有一个weak引用指向对象,则释放对象,且自动设置该weak指针为nil。
3.3、copy:赋值时将拷贝对象,仅对实现了NSCopying协议的对象使用。对包含可变子类的类类型对象使用。例如NSString类的可变子类NSMutableString。NSMutableArray具有可变子类NSMutableArray。至于copy的所有权则是强引用类型的。
对于copy方法,不可变类型的copy方法返回对象本身,可变类型才会真正执行复制:
@interface Item : NSObject
@property (copy,nonatomic) NSString* itemName;
@end
以下测试代码:
NSMutableString* strName=[[NSMutableString alloc ] initWithString:@“ItemBook”];
Items* book=[[Items alloc] init];
[book setItemName:strName];
NSLog(@"address of strName=%p,address of itemName Property=%p",strName,[book itemName]);
输出:address of strName=0x100307630,address of itemName Property=0x344006bc30d285
而将strName改为NSString(不可变字符串)时输出为:
NSString* strName=[[NSString alloc ] initWithString:@"ItemBook"];
address of strName=0x1000030e8,address of itemName Property=0x1000030e8
注意:
NSString* strName=[[NSMutableString alloc ] initWithString:@“ItemBook"];
输出为:
address of strName=0x1002089d0,address of itemName Property=0x344006bc30d285
即向不可变类型发送copy消息时,将直接返回原地址,避免不必要的开销。
复制可变类型时将执行真正复制。
3.4、assign:默认,直接赋值,用于数量类型。例如NSInteger,CGRect等。
二、强引用循环
两个类互相持有对方的strong引用时,将导致两者都无法释放:
Parent类.h:
@class Parent;
@interface Son : NSObject
@property(nonatomic,strong) Parent* parent;
@end
Parent类.m:
#import "Parent.h"
@implementation Parent
-(void) dealloc{
NSLog(@"delloc Parent");
}
@end
Son类.h:
#import <Foundation/Foundation.h>
@class Parent;
@interface Son : NSObject
@property(nonatomic,strong) Parent* parent;
@end
Son类.m:
#import "Son.h"
@implementation Son
-(void) dealloc{
NSLog(@"delloc son");
}
@end
测试代码:
int main(int argc, const char * argv[]) {
@autoreleasepool {
Parent* parent=[[Parent alloc] init];
Son* son=[[Son alloc] init];
[parent setSon:son];
[son setParent: parent];
}
return 0;
}
无输出,对于这种情况,应该将Son类的parent属性修改为weak。
三、ARC使用规则:
1.不能直接调用dealloc方法,不能调用retain,release,autorelease,retainCount方法,包括@selector(retain)的方式也不行。
2.可以用dealloc方法来管理一些资源,但不能用来释放实例变量,也不能在dealloc方法里面调用[super dealloc]方法。
3.Core Foundation类型的对象仍然可以用CFRetain,CFRelease这些方法。
4.不能再使用NSAllocateObject和NSDeallocateObject方法。
5.不能在C结构体中使用对象指针。
6.在id和void*之间没有简便的转换方法,同样在Objective-C和Core Foundation类型之间的转换都需要使用指定(__bridge,__bridge_transfer,__bridge_retained)的转换函数。
7.不能再使用NSAutoreleasePool对象,ARC提供了@autoreleasepool块来代替它。
8.不能使用内存存储区(不能再使用NSZone)。
9.不能以new为开头给一个属性命名。
10.声明IBOutlet时一般应当使用weak,除了对StoryBoard这样nib中间的顶层对象要用strong。