objective c:循環引用

談談OC中的循環引用

1.什麼時候會發生循環引用

將一個提前準備好的代碼塊, 在需要執行的時候立即執行, 在不需要立即執行的時候, 用個屬性將這個函數傳遞過來的block記錄下來, 產生了強引用, 此時就會發生循環引用

2.怎麼解決循環引用

那麼怎麼解決循環引用, 就是打破任一方的強引用

1240

.

  • 其中使用最多的就是weak, 聲明一個弱引用類型的自己, 解除循環引用, 其中weak跟weak類似, 當對象被系統回收時, 它的內存地址會自動指向nil, 對nil進行任何操作不會有反應

  • 但其實在ios4的時候, 也可以使用__unsafe_unretained, 解除強引用, 但是它存在一定的不安全性, 原理和assign類似, 當對象被系統回收時, 它的內存地址不會自動指向nil, 就有可能出現壞內存地址的訪問, 也就發生野指針錯誤

  • 在之前發現了很多解除循環引用的時候, 會先使用weak, 聲明自己爲弱引用類型, 然後在準備好的代碼塊中也就是block中, 再對弱引用對象利用strong 做一次強操作 , 仔細驗證發現再做強引用操作是冗餘的, 並不會產生影響, 可以不用寫

3.如何驗證是否發生循環引用

1240

.

4.simple demo

#import "ViewController.h"#import "NetworkTools.h"@interface ViewController ()@property (nonatomic, strong) NetworkTools *tools;@end@implementation ViewController- (void)viewDidLoad {
    [super viewDidLoad];    self.tools = [[NetworkTools alloc] init];/*
    //解決方式三: __unsafe_unretained 不推薦, 不安全
    __unsafe_unretained typeof(self) weakSelf = self;
    [self.tools loadData:^(NSString *html) {
        __strong typeof(self) strongSelf = weakSelf;
        NSLog(@"%@%@",html,strongSelf.view);
        strongSelf.view.backgroundColor = [UIColor redColor];
    }];
*/

    //解決方式二: __weak
    __weak typeof(self) weakSelf = self;
    [self.tools loadData:^(NSString *html) {
        __strong typeof(self) strongSelf = weakSelf;        NSLog(@"%@%@",html,strongSelf.view);
        strongSelf.view.backgroundColor = [UIColor redColor];
    }];

}//解決方式一: - (void) method1{
    NetworkTools *tools = [[NetworkTools alloc] init];
    [tools loadData:^(NSString *html) {        NSLog(@"%@%@",html,self.view);        self.view.backgroundColor = [UIColor redColor];
    }];
}

- (void)dealloc {    NSLog(@"VC dealloc");
}@end
#import "NetworkTools.h"@interface NetworkTools ()//用一個屬性 來記錄 函數傳遞過來的 block@property (nonatomic, copy) void(^finishedBlock)(NSString *);@end@implementation NetworkTools- (void)loadData:(void (^)(NSString *))finishedCallBack {    //開始記錄blcok
    self.finishedBlock = finishedCallBack;    dispatch_async(dispatch_get_global_queue(0, 0), ^{

        [NSThread sleepForTimeInterval:3];        //開始耗時任務
        NSLog(@"開始加載數據");        dispatch_async(dispatch_get_main_queue(), ^{            //調用方法
            [self working];
        });
    }); 
}

- (void) working {    //執行block
    if (self.finishedBlock) {        self.finishedBlock(@"<html>");
    }
}

- (void)dealloc {    NSLog(@"Tools dealloc");
}@end

推薦 鄰家菇涼 的文章《談談OC中的循環引用》( 分享自 @簡書 )

http://www.jianshu.com/p/48b3d47fac12

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章