美文网首页iOS基础修炼iOS技术文章
OC:copy/strong/weak..使用总结☀️

OC:copy/strong/weak..使用总结☀️

作者: LeaderBiao | 来源:发表于2016-06-24 11:40 被阅读642次
    • 版权声明:本文为博主原创文章,未经博主允许不得转载。
    • 原文档关于自动引用说明:

    Automatic Reference Counting (ARC) is a compiler feature that provides automatic memory management of Objective-C objects. Rather than having to think about retain and release operations, ARC allows you to concentrate on the interesting code, the object graphs, and the relationships between objects in your application.

    • 翻译过来就是:
      Automatic Reference Counting (ARC)是一个编译器的特性,提供了对iOS对象的自动内存管理,ARC在编译期间自动在适当的地方添加ObjC对象的retainrelease操作代码,而不需要我们关心。

    ARC在编译期间,根据Objective-C对象的存活周期,在适当的位置添加retain和release代码。从概念上讲,ARC与手动引用计数内存管理遵循同样的内存管理规则,但是ARC也无法防止循环强引用。

    ARC还引入了新的修饰符来修饰变量和声明属性。
        ·   声明变量的修饰符:__strong, __weak, __unsafe_unretained, __autoreleasing;
        ·   声明属性的修饰符:strong, weak, unsafe_unretained。
        ·   对象和Core Foundation-style对象直接的转换修饰符号:__bridge,__bridge_retained或CFBridgingRetain, __bridge_transfer或CFBridgingRelease。
        ·   对于线程的安全,有nonatomic,这样效率就更高了,但是不是线程的。如果要线程安全,可以使用atomic,这样在访问是就会有线程锁。```
    
    #####记住内存管理法则:谁使对象的引用计数+1,不再引用时,谁就负责将该对象的引用计数-1。
    
    
    - 下面我们来声明一个Person类来学习:
    
    ```swift
    @interface Person : NSObject
    
    // 注意:苹果有命名规范的,命名属性时,不能以copy开头。
    // 如果下面的属性声明为copyString,会编译不通过。
    @property (nonatomic, copy) NSString *copiedString;
    
    // 默认会是什么呢?
    @property (nonatomic) NSString *name;
    // 默认是strong类型
    @property (nonatomic) NSArray *array;
    
    @end```
    
    如果属性没有指定类型,默认是什么呢?其实是`strong`。如果证明呢?验证方法:分别将array属性的类型分别设置为`weak, assign,strong`,不设置,这四种情况的结果分别是:第一种打印为空,第二种直接直接崩溃,第三种和最后一种是可以正常使用。如下面的验证代码:
    

    Person *lili = [[Person alloc] init];
    lili.name = @"LiLi";
    lili.copiedString = @"LiLi' father is LLL";
    lili.array = @[@"谢谢", @"感谢"];

    NSArray *otherArray = lili.array;
    lili = nil;
    NSLog(@"%@", otherArray);

    
    再继续添加下面的代码。默认声明变量的类型为`__strong`类型,因此上面的`NSArray *otherArray = lili.array;`与`__strong NSArray *otherArray = lili.array;`是一样的。如果我们要使用弱引用,特别是在解决循环强引用时就特别重要了。我们可以使用`__weak`声明变量为弱引用,这样就不会增加引用计数值。
    

    __strong NSArray *strongArray = otherArray;
    otherArray = nil;
    // 打印出来正常的结果。
    NSLog(@"strongArray = %@", strongArray);

    __weak NSArray * weakArray = strongArray;
    strongArray = nil;
    // 打印出来:null
    NSLog(@"weakArray: %@", weakArray);```

    xib/storybard连接的对象为什么可以使用weak?
    @property (nonatomic, weak) IBOutlet UIButton *button;
    

    像上面这行代码一样,在连接时自动生成为weak。因为这个button已经放到view上了,因此只要这个View不被释放,这个button的引用计数都不会为0,因此这里可以使用weak引用。

    如果我们不使用xib/storyboard,而是使用纯代码创建呢?
    @property (nonatomic, weak) UIButton *button;```
    
    >使用weak时,由于button在创建时,没有任何`强引用`,因此就有可能提前释放。Xcode编译器会告诉我们,这里不能使用weak。因此我们需要记住,只要我们在创建以后需要使用它,我们必须保证至少有一个强引用,否则引用计数为0,就会被释放掉。对于上面的代码,就是由于在创建时使用了weak引用,因此button的引用计数仍然为0,也就是会被释放,编译器在编译时会检测出来的。
    
    这样写,在创建时通过`self.button = ...`就是出现错误,因为这是弱引用。所以我们需要声明为强引用,也就是这样:
    

    @property (nonatomic, strong) UIButton *button;```

    block声明使用copy.

    在使用block时,尽量使用typedef来起一个别名,这样更容易阅读。

    使block作为属性时,使用copy

    typedef void (^Block)(NSString *name);
    
    @property (nonatomic, copy) Block testBlock;```
    
    #####属性声明修饰符
    
    
    - 属性声明修饰符有:`strong, weak, unsafe_unretained, readWrite`,默认`strong`, `readWrite`的。
        ·   `strong`:`strong`和`retain`相似,只要有一个strong指针指向对象,该对象就`不会被销毁`
        ·   `weak`:声明为`weak`的指针,`weak`指针指向的对象一旦被释放,`weak`的指针都将被赋值为`nil`;
        ·   `unsafe_unretained`:用`unsafe_unretained`声明的指针,指针指向的对象一旦被释放,这些指针将成为野指针。
    
    

    @property (nonatomic, copy) NSString *name;
    // 一旦所指向的对象被释放,就会成为野指针
    @property (nonatomic, unsafe_unretained) NSString *unsafeName;

    lili.name = @"Lili";
    lili.unsafeName = lili.name;
    lili.name = nil;
    // unsafeName就变成了野指针。这里不会崩溃,因为为nil.
    NSLog(@"%@", lili.unsafeName);```

    总结

    • 关于属性的这些选项的学习,做一下总结:
        ·   所有的属性,都尽可能使用nonatomic,以提高效率,除非真的有必要考虑线程安全。
        ·   NSString:通常都使用copy,以得到新的内存分配,而不只是原来的引用。
        ·   strong:对于继承于NSObject类型的对象,若要声明为强使用,使用strong,若要使用弱引用,使用__weak来引用,用于解决循环强引用的问题。
        ·   weak:对于xib上的控件引用,可以使用weak,也可以使用strong。
        ·   __weak:对于变量的声明,如果要使用弱引用,可以使用__weak,如:__weak typeof(Model) weakModel = model;就可以直接使用weakModel了。
        ·   __strong:对于变量的声明,如果要使用强引用,可以使用__strong,默认就是__strong,因此不写与写__strong声明都是一样的。
        ·   unsafe_unretained:这个是比较少用的,几乎没有使用到。在所引用的对象被释放后,该指针就成了野指针,不好控制。
        ·   __unsafe_unretained:也是很少使用。同上。
        ·   __autoreleasing:如果要在循环过程中就释放,可以手动使用__autoreleasing来声明将之放到自动释放池。```

    相关文章

      网友评论

        本文标题:OC:copy/strong/weak..使用总结☀️

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