iOS開發中的 ARC

1. weak屬性(弱引用)ios

被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

打印信息:post

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

被__weak修飾的對象也是弱引用,以下所示,其打印信息也爲nilatom

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

 

2. strong屬性(強引用)spa

被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] strongcode

默認方式建立的對象以及__strong方式修飾的對象都是強引用,其打印信息是"strong"orm

-默認方式-

    // 賦值
    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.

相關文章
相關標籤/搜索