ios-weak和strong的使用

weak:修飾屬性,對屬性賦值的時候不會對對象retain,引用計數(shù)也不會+1,并且當(dāng)所引用的對象為nil時,該屬性也就變?yōu)閚il
strong:與weak 不同,strong修飾屬性,對屬性賦值時,會對對象retain,并且應(yīng)用計數(shù)會+1.
在項目開發(fā)中,要值得注意的就是block中,_weak和_strong的使用。下面我們來具體幾個實例方便理解

 FirstViewController *firstVC=[FirstViewController new];
    NSLog(@"block之前 rataincount:%zd",CFGetRetainCount((__bridge CFTypeRef)(self)));
    firstVC.firstBlock = ^(NSString *str) {
       
        
    };
    NSLog(@"block之后 rataincount:%zd",CFGetRetainCount((__bridge CFTypeRef)(self)));
    [self.navigationController pushViewController:firstVC animated:YES];

打印的結(jié)果是:

block之前 rataincount:5
block之后 rataincount:7

發(fā)現(xiàn)并不是+1,而是+2了。這是由于block在創(chuàng)建的時候在堆上,而賦值給全局變量的時候,拷貝到棧上了。由于block對這個對象的強引用,就導(dǎo)致了,只要block不釋放,那么所引用的對象也就沒辦法釋放-1.導(dǎo)致對象的delloc方法無法執(zhí)行。
然后我們在執(zhí)行一段代碼發(fā)現(xiàn)

FirstViewController *firstVC=[FirstViewController new];
    NSLog(@"block之前 rataincount:%zd",CFGetRetainCount((__bridge CFTypeRef)(self)));
    __weak typeof(self) wself = self;
    firstVC.firstBlock = ^(NSString *str) {
       
        
    };
    NSLog(@"block之后 rataincount:%zd",CFGetRetainCount((__bridge CFTypeRef)(self)));
    [self.navigationController pushViewController:firstVC animated:YES];

2021-03-02 14:56:59.214961+0800 RuntimeDemo[20368:7840960] block之前 rataincount:5
2021-03-02 14:56:59.215105+0800 RuntimeDemo[20368:7840960] block之后 rataincount:5

在block中調(diào)用函數(shù)時,又是什么情況

FirstViewController *firstVC=[FirstViewController new];
    NSLog(@"block之前 rataincount:%zd",CFGetRetainCount((__bridge CFTypeRef)(self)));
    __weak typeof(self) wself = self;
    firstVC.firstBlock = ^(NSString *str) {
        
        [wself textNameWith:str];
    };
    NSLog(@"block之后 rataincount:%zd",CFGetRetainCount((__bridge CFTypeRef)(self)));
    [self presentViewController:firstVC animated:YES completion:^{
    }];
2021-03-02 15:05:50.179184+0800 RuntimeDemo[20376:7844250] block之前 rataincount:5
2021-03-02 15:05:50.179469+0800 RuntimeDemo[20376:7844250] block之后 rataincount:5

再來看網(wǎng)上的一個例子:

TestObj *obj = [[TestObj alloc] init];
__weak TestObj *weakObj = obj;
NSLog(@"before block retainCount:%zd",[obj arcDebugRetainCount]);
block = ^(){
    NSLog(@"TestObj對象地址:%@",weakObj);
    dispatch_async(dispatch_queue_create(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^{
        
        for (int i = 0; i < 1000000; i++) {
            // 模擬一個耗時的任務(wù)
        }

        NSLog(@"耗時的任務(wù) 結(jié)束 TestObj對象地址:%@",weakObj);
    });
};
NSLog(@"after block retainCount:%zd",[obj arcDebugRetainCount]);
block();
輸出結(jié)果:
before block retainCount:1
after block retainCount:1
TestObj對象地址:<TestObj: 0x602000006af0>
TestObj 對象已釋放
 耗時的任務(wù) 結(jié)束 TestObj對象地址:(null)

在這個線程之前是沒有被釋放的,但是當(dāng)執(zhí)行完耗時任務(wù)的時候,對象是被釋放了。
而要解決這個問題 需要 __strong TestObj *strongObj = weakObj;這樣耗時任務(wù)之后就不會被釋放

__weak 修飾的對象被block引用,不會影響釋放。而__strong在Block內(nèi)部修飾的對象,會保證在使用這個對象在scope內(nèi),這個對象都不會被釋放,出了scope,引用計數(shù)就會-1,且__strong主要是用在多線程運用中,若果只使用單線程,只需要使用__weak就行。

那么block中嵌套,又應(yīng)該怎么修飾呢

LHRModel *model = [LHRModel new];
   
    __weak typeof(self) weakSelf = self;
    model.dataChanged = ^(NSString *title) {
        __strong typeof(self) strongSelf = weakSelf;
        strongSelf.titleLabel.text = title;
        
        __weak typeof(self) weakSelf2 = strongSelf;
        strongSelf.model.dataChanged = ^(NSString *title2) {
            __strong typeof(self) strongSelf2 = weakSelf2;
            strongSelf2.titleLabel.text = title2;
        };
    };

這樣就可以避免循環(huán)引用

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容