• iOS开发中的 ARC


    1. weak属性(弱引用)

    被weak修饰的对象叫弱引用,不算对象持有者,一个方法执行完后会导致这个对象自动释放掉,并将对象的指针设置成nil,我使用GCD延时1000ms来验证,1000ms之后,其对象是否还在.

    #import "RootViewController.h"
    
    @interface RootViewController ()
    
    @property (nonatomic, weak) NSString *str;
    
    @end
    
    @implementation RootViewController
    
    /**
     延时多少毫秒
     
     @param microseconds 毫秒
     @param queue 线程池
     @param block 执行代码处
     @return none
     */
    - (void)delayTime:(int64_t)microSeconds inQueue:(dispatch_queue_t)queue
                block:(void (^)(dispatch_queue_t queue))block
    {
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, microSeconds * USEC_PER_SEC);
        dispatch_after(popTime, queue, ^(void){
            block(queue);
        });
    }
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        // 赋值
        _str = [NSString stringWithFormat:@"weak"];
        
        // 延时1000毫秒
        [self delayTime:1000
                inQueue:dispatch_get_main_queue()
                  block:^(dispatch_queue_t queue) {
                      NSLog(@"%@", _str);
                  }];
    }
    
    @end

    打印信息:

    2014-03-31 14:48:29.360 ARC[3387:60b] (null)

    被__weak修饰的对象也是弱引用,如下所示,其打印信息也为nil

        // 赋值
        __weak NSString *str = [NSString stringWithFormat:@"weak"];
        
        // 延时1000毫秒
        [self delayTime:1000
                inQueue:dispatch_get_main_queue()
                  block:^(dispatch_queue_t queue) {
                      NSLog(@"%@", str);
                  }];

    2. strong属性(强引用)

    被strong修饰的对象叫强引用,是对象持有者,一个方法执行完后这个对象不会被释放,我使用GCD延时1000ms来验证,1000ms之后,其对象是否还在.

    #import "RootViewController.h"
    
    @interface RootViewController ()
    
    @property (nonatomic, strong) NSString *str;
    
    @end
    
    @implementation RootViewController
    
    /**
     延时多少毫秒
     
     @param microseconds 毫秒
     @param queue 线程池
     @param block 执行代码处
     @return none
     */
    - (void)delayTime:(int64_t)microSeconds inQueue:(dispatch_queue_t)queue
                block:(void (^)(dispatch_queue_t queue))block
    {
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, microSeconds * USEC_PER_SEC);
        dispatch_after(popTime, queue, ^(void){
            block(queue);
        });
    }
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        // 赋值
        _str = [NSString stringWithFormat:@"strong"];
        
        // 延时1000毫秒
        [self delayTime:1000
                inQueue:dispatch_get_main_queue()
                  block:^(dispatch_queue_t queue) {
                      NSLog(@"%@", _str);
                  }];
    }
    
    @end

    打印信息:

    2014-03-31 14:59:57.445 ARC[3599:60b] strong

    默认方式创建的对象以及__strong方式修饰的对象都是强引用,其打印信息是"strong"

    -默认方式-

        // 赋值
        NSString *str = [NSString stringWithFormat:@"strong"];
        
        // 延时1000毫秒
        [self delayTime:1000
                inQueue:dispatch_get_main_queue()
                  block:^(dispatch_queue_t queue) {
                      NSLog(@"%@", str);
                  }];

    -__strong修饰方式-

        // 赋值
        __strong NSString *str = [NSString stringWithFormat:@"strong"];
        
        // 延时1000毫秒
        [self delayTime:1000
                inQueue:dispatch_get_main_queue()
                  block:^(dispatch_queue_t queue) {
                      NSLog(@"%@", str);
                  }];

    strong修饰的对象没有释放,则weak还是可以用的

        // 赋值
        NSString *str = [NSString stringWithFormat:@"strong"];
        __weak NSString *tmp = str;
        
        // 延时1000毫秒
        [self delayTime:1000
                inQueue:dispatch_get_main_queue()
                  block:^(dispatch_queue_t queue) {
                      NSLog(@"%@", tmp);
                      NSLog(@"%@", str);
                  }];

    打印信息:

    2014-03-31 15:27:48.894 ARC[4144:60b] strong
    2014-03-31 15:27:48.897 ARC[4144:60b] strong

    以下例子按理说stringTest中retStr属于强引用,但其值赋给tmp时,却打印为nil,为什么呢?

    ARC下,当一个函数返回一个NSObject指针时,编译器会帮我们实现autorelease调用,也就是retStr与返回值不是一个东西了.

    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        // 赋值
        NSString *str = [NSString stringWithFormat:@"strong"];
        __weak NSString *tmp = [self stringTest];
        
        // 延时1000毫秒
        [self delayTime:1000
                inQueue:dispatch_get_main_queue()
                  block:^(dispatch_queue_t queue) {
                      NSLog(@"%@", tmp);
                      NSLog(@"%@", str);
                  }];
    }
    
    - (NSString *)stringTest
    {
        __strong NSString *retStr = [NSString stringWithFormat:@"strongVer2"];
        
        // 延时1000毫秒
        [self delayTime:1000
                inQueue:dispatch_get_main_queue()
                  block:^(dispatch_queue_t queue) {
                      NSLog(@"%@", retStr);
                  }];
        
        return retStr;
    }

    打印信息:

    2014-03-31 15:30:19.185 ARC[4172:60b] strongVer2
    2014-03-31 15:30:19.188 ARC[4172:60b] (null)
    2014-03-31 15:30:19.188 ARC[4172:60b] strong

    3. __unsafe_unretained

    该关键字与__weak一样,也是弱引用,与__weak的区别只是是否执行nil赋值。需要注意变量所指的对象已经被释放了,但地址还存在,如果还是访问该对象,将引起「BAD_ACCESS」错误。

    4. __autoreleasing

    本人并没有明白__autoreleasing有什么作用,看例子也没明白,提供链接供读者参考

    http://stackoverflow.com/questions/20949886/need-more-explanation-on-usage-of-autoreleasing

    'm desperately trying to understand the usage of __autoreleasing keyword in Objective-C. I have thoroughly read answers to the following questions:

    In which situations do we need to write the __autoreleasing ownership qualifier under ARC?

    Use of __autoreleasing in code snippet example

    NSError and __autoreleasing

    问:非arc项目中使用了arc编译的静态库,为什么不会报警告?

    http://stackoverflow.com/questions/18609935/strong-qualifier-used-in-non-arc-project

    The project is non-ARC enabled, however we are (mistakingly) using ARC compliant code libraries - specifically one to create singleton objects like so defined in GCDSingleton.h:

    我的项目是非arc的,然而,我无意间使用了用arc编译的库,尤其是其中的一个单例对象,在GCDSingleton.h文件中定义的:

    #define DEFINE_SHARED_INSTANCE
    +(id)sharedInstance
    {staticdispatch_once_t pred =0;
      __strong static id _sharedObject = nil;
      dispatch_once(&pred,^{
        _sharedObject =^{return[[self alloc] init];}();});return _sharedObject;}

    This seems to work even though the shared object is defined with an __strong qualifier. I'm wondering why this doesn't cause an error or at least a warning (latest Xcode 4.6 and ios 6 sdk). Also, since the project is not ARC enabled, what exactly is that __strong qualifier doing, if anything?

    即使这个对象被定义成了__strong,但还是可以使用.我在想,为什么不会引起一个警告.__strong在非arc项目中到底做了什么,任何一点解释都行.

    ------------------------------------------------------------------------------------------------------------------

    In MRC code, __strong is simply ignored.

    在非arc代码中,__strong被忽略掉了.

    I tried to compile a simple example

    #import <Foundation/Foundation.h>

    int main(int argc,charconst*argv[]){ __strong NSString* foo =[[NSString alloc] initWithFormat:@"Hello, %s", argv[1]];
    NSLog(@"%@", foo);
    }

    with ARC

    clang -fobjc-arc test.m -S -emit-llvm -o arc.ir

    and without ARC

    clang -fno-objc-arc test.m -S -emit-llvm -o mrc.ir

    and to diff the llvm IR output.

    Here's the result of diff mrc.ir arc.ir

    54a55,56>%17= bitcast %0**%foo to i8**>   call void@objc_storeStrong(i8**%17, i8* null) nounwind
    63a66,67> declare void@objc_storeStrong(i8**, i8*)>

    So basically the only difference between ARC and MRC is the addition of a objc_storeStrong call.


    By the way the same code without the __strong qualifier will produce the same exact results, since __strong is the default qualifier for variables in ARC.

  • 相关阅读:
    回溯算法总结
    第四章总结
    第四章编程总结
    动态规划总结:
    第三章实践心得
    分治算法体会
    第二章上机实践总结
    代码规范与《数学之美》读后感
    第二次c++作业
    第一次博客作业
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/3635933.html
Copyright © 2020-2023  润新知