Objective-C属性详解(附代码)

声明

在Objective-C中,有两种声明变量的方法,第一种直接声明:

@interface Person : NSObject
{
    NSString *name;
    NSString *sex;
    NSString *age;
    Hand *hands[2];
    Foot *foots[2];

}

第二种可以使用属性,关键字@property,顾名思义,属性就是将变量看作是类的属性:

@interface Person : NSObject
{
    
    NSString *name;
    NSString *sex;
    NSString *age;
    Hand *hands[2];
    Foot *foots[2];

}
@property Foot* leftfoot;
@property Foot* rightfoot;
@property Hand* lefthand;
@property Hand* righthand;

属性与直接声明变量不同的地方在于,如果直接声明,在外面要想访问name,需要设置他的setter,getter方法,不能直接访问。
如果使用属性的方法,可以这样进行访问

Person *person = [Person new];
person.leftfoot = [Foot new];
[person setLeftfoot:[Foot new]];
Foot *foot1 = [person leftfoot];
Foot *foot2 = person.leftfoot;

如果实在类的内部可以像这样访问:

-(void)desc{
    [self.leftfoot desc];
    [_leftfoot desc];   
}

self.leftfoot与_leftfoot的访问效果是一样的。

属性的参数

属性的声明是可以带参数的,如下:

@property (nonatomic,strong) Foot* leftfoot;

nonatomic和strong都是属性的参数,代表参数的一些特性:

atomic和nonatomic

atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作。
设置成员变量的@property属性时,默认为atomic,提供多线程安全。
nonatomic禁止多线程,变量保护,提高性能。

assign与retain

  1. 接触过C,那么假设你用malloc分配了一块内存,并且把它的地址赋值给了指针a,后来你希望指针b也共享这块内存,于是你又把a赋值给(assign)了b。此时a和b指向同一块内存,请问当a不再需要这块内存,能否直接释放它?答案是否定的,因为a并不知道b是否还在使用这块内存,如果a释放了,那么b在使用这块内存的时候会引起程序crash掉。
  2. 了解到1中assign的问题,那么如何解决?最简单的一个方法就是使用引用计数(reference counting),还是上面的那个例子,我们给那块内存设一个引用计数,当内存被分配并且赋值给a时,引用计数是1。当把a赋值给b时引用计数增加到2。这时如果a不再使用这块内存,它只需要把引用计数减1,表明自己不再拥有这块内存。b不再使用这块内存时也把引用计数减1。当引用计数变为0的时候,代表该内存不再被任何指针所引用,系统可以把它直接释放掉。总结:上面两点其实就是assign和retain的区别,assign就是直接赋值,从而可能引起1中的问题,当数据为int, float等原生类型时,可以使用assign。retain就如2中所述,使用了引用计数,retain引起引用计数加1, release引起引用计数减1,当引用计数为0时,dealloc函数被调用,内存被回收。
@property (nonatomic,assign) Foot* leftfoot;
@property (nonatomic,retain) Foot* rightfoot;
person.leftfoot = [Foot new];
person.rightfoot = [Foot new];
Foot *foot1 = person.leftfoot;
Foot *foot2 = person.rightfoot;

这是对于leftfoot,编译器就会爆出warning:

/Users/umeng/iosdev/Foundation/Foundation/main.m:17:25: Assigning retained object to unsafe property; object will be released after assignment

copy与retain

关于copy与retain,其实都会在赋值的时候,先释放,但是一个是执行copy,一个是执行retain,这里举个例子,可能大家就明白了:

@property (nonatomic,copy) NSString* test;
@property (nonatomic,retain) NSString* test2;

然后进行赋值:

 NSMutableString *s = [[NSMutableString alloc]initWithString:@"hello"];
        Person *person = [Person new];
        person.test =s;
        person.test2 =s ;
        [s appendString:@" world"];
NSLog(@"%@:%@",person.test,person.test2);

结果:

《Objective-C属性详解(附代码)》 Paste_Image.png

weak与strong

weak 和 strong 属性只有在你打开ARC时才会被要求使用,这时你是不能使用retain release autorelease 操作的,因为ARC会自动为你做好这些操作,但是你需要在对象属性上使用weak 和strong,其中strong就相当于retain属性,而weak相当于assign。

readwrite与readonly

readwrite 是可读可写特性;需要生成getter方法和setter方法时使用。
readonly 是只读特性 ,只会生成getter方法,不会生成setter方法 ;不希望属性在类外改变。
对比代码效果更好一些,我将代码放在了github上:
https://github.com/mymdeep/OC_foundation
*更多的开发知识,可以关注我的公众号:

《Objective-C属性详解(附代码)》

    原文作者:mymdeep
    原文地址: https://www.jianshu.com/p/fc388c7b7503
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞