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

作者: mymdeep | 来源:发表于2017-01-14 15:34 被阅读36次

    声明

    在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);
    

    结果:

    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属性详解(附代码)

        本文链接:https://www.haomeiwen.com/subject/sgpebttx.html