iOS--property属性常用的关键字

在开发中,我们iOS在定义属性的时候,需要在括号property()内说明该属性的特性,因为属性的特性决定了属性在原子性、存取方法、内存管理三个方面的特性。首先属性property有两大概念:ivar(实例变量)、存取方法(access method=getter),即@property = ivar + getter + setter。如:

@property(nonatomic,copy)NSString *name;

类完成属性的定以后,编译器会自动编写访问这些属性的方法(自动合成autosynthesis),上述代码写出来的类等效与下面的代码:

- (NSString *)name;  
- (void)setName:(NSString *)name;

再看看常用的特性关键字,大概有9个,分为原子性、存取方法、内存管理三组:

1、nonatomic / atomic
2、readonly / readwrite
3、retain / copy / strong /weak / assign

下面我们就分别看下这几个关键字:

原子性:(nonatomic / atomic)

atomic(系统默认):atomic,提供多线程安全,在多线程环境下,原子操作是必要的,否则有可能引起错误的结果。加了atomic,setter函数会变成下面这样:

@property(retain) UITextField *userName;

//系统生成的代码如下:
- (UITextField *) userName {
    UITextField *retval = nil;
    @synchronized(self) {
        retval = [[userName retain] autorelease];
    }
    return retval;
}

- (void) setUserName:(UITextField *)userName_ {
    @synchronized(self) {
      [userName release];
      userName = [userName_ retain];
    }
}

多线程中只能有一个线程能对它进行访问该变量为线程安全型,但是会影响访问速度,在非ARC编译环境下,需要设置访问锁来保证对该变量进行正确的getter/setter。

nonatomic(常用):nonatomic跟atomic刚好相反,表示非原子的,可以被多个线程访问。它的效率比atomic快,但不能保证在多线程环境下的安全性,在单线程和明确只有一个线程访问的情况下广泛使用。多个线程可以同时对其进行访问,访问速度快;当一个变量声明为nonatomic时,setter函数会变成下面这样:

@property(nonatomic, retain) UITextField *userName;

//系统生成的代码如下:
- (UITextField *) userName {
    return userName;
}

- (void) setUserName:(UITextField *)userName_ {
    [userName_ retain];
    [userName release];
    userName = userName_;
}

atomic是Objc使用的一种线程保护技术,基本上来讲,是防止在写未完成的时候被另外一个线程读取,造成数据错误。而这种机制是耗费系统资源的,所以在iPhone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择;那居然我们一般都是用nonatomic ,那系统为什么还是默认用atomic 呢?这是因为iOS 用 nonatomic 比较好,而 OSX 用 atomic相对较好。如果不写的话,系统按照相对比较安全的 atomic 处理。iOS 用nonatomic主要是出于性能考虑,OSX 上性能不是问题,所以使用了atomic。

注意:
  atomic的作用只是给getter和setter加了个锁,atomic只能保证代码进入getter或者setter函数内部时是安全的,一旦出了getter和setter,多线程安全只能靠程序员自己保障了。所以atomic属性和使用property的多线程安全并没什么直接的联系。另外,atomic由于加锁也会带来一些性能损耗,所以我们在编写iOS代码的时候,一般声明property为nonatomic,在需要做多线程安全的场景,自己去额外加锁做同步。

存取方法:(readonly / readwrite)

从字面上看的出来,意思很简单:

readwrite(系统默认):可读可写,表示该属性同时拥有setter和getter。

设置器和读取器都需要在@implementation中实现。如果使用@synthesize关键字,读取器和设置器都会被解析。

readonly:只读属性,表示只有getter没有setter,不希望属性在类外改变;

如果你指定了只读,在@implementation中只需要一个读取器。或者如果你使用@synthesize关键字,也是有读取器方法被解析。而且如果你试图使用点操作符为属性赋值,你将得到一个编译错误。

内存管理(retain 、copy 、strong、weak、assign)

retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1,对其他NSObject和其子类,对参数进行release旧值,再retain新值,指定retain会在赋值时唤醒传入值的retain消息。此属性只能用于Objective-C对象类型,而不能用于Core Foundation对象。使用:对其他NSObject和其子类;

copy: setter方法进行copy操作,与retain处理流程一样,先旧值release,再copy出新的对象,retainCount为1。这是为了减少对上下文的依赖而引入的机制。 copy是在你不希望a和b共享一块内存时会使用到。a和b各自有自己的内存。retain是指针拷贝,copy是内容拷贝;使用:NSString,NSArray,NSDictionary及其可变子类;

注意:当类拥有mutable子类时,你应该使用copy,而不是retain。
例如:NSAArray,NSSet,NSDictionary,NSData的,NSCharacterSet,NSIndexSet,NSString;

strong(ARC中默认):强引用,表示实例变量对传入的对象要有所有权关系;在ARC环境下等同于retain;使用:自定义对象,控制器对象;比如我们传Model的时候必须用strong,否则会崩溃!

weak:弱引用,在setter方法中,需要对传入的对象不进行引用计数加1的操作。简单来说,就是对传入的对象没有所有权,当该对象引用计数为0时,即该对象被释放后,用weak声明的实例变量指向nil,即实例变量的值为0。使用:代理对象,IBOutlet;

assign: 简单赋值,不更改索引计数,适用简单数据类型。使用:int、float、double和NSInteger,CGFloat等;

声明: 转载请注明出处http://www.jianshu.com/p/c2d51763d164

你可能感兴趣的:(iOS--property属性常用的关键字)