PS:雖然確實很忙,但自己確實變懶了,又好久沒有寫文章啦~~~
下面記一篇開發(fā)過程中的小事,新來的人看了下面這段代碼 又問我有了weakSelf 為什么還要加一個strongSelf。
__weak __typeof(&*self)weakSelf = self;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
__strong __typeof(weakSelf) strongSelf = weakSelf;
/**
**/
});
weakSelf只是弱引用,self對象被釋放后,獲取該對象也會被釋放,它的屬性會為空。
block內(nèi)strongSelf對weakSelf做了一層強引用,避免weakSelf被釋放掉。
也許這樣的解釋比較抽象。
下面跑幾段代碼來看看
#define PBLog(prefix,Obj) {NSLog(@"%@::: 變量值:%p, 指向?qū)ο笾担?@",prefix,Obj,Obj);}
- (void)testForNOStrongSelf
{
MyTestForBlock *obj = [[MyTestForBlock alloc]init];
obj.testText = @"TestForBlock";
PBLog(@"obj", obj);
__weak MyTestForBlock *weakObj = obj;
PBLog(@"weakObj", weakObj);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
PBLog(@"obj 釋放前 weakObj", weakObj);
sleep(2);
NSLog(@"weakObj.testText::%@",weakObj.testText);
PBLog(@"obj 釋放后block內(nèi) weakObj", weakObj);
});
sleep(1);
obj = nil;
PBLog(@"obj 釋放后 weakObj", weakObj);
}
控制臺輸出:
2017-08-21 18:41:00.866 TestForBlock[20598:453239] obj::: 變量值:0x608000016830, 指向?qū)ο笾担?lt;MyTestForBlock: 0x608000016830>
2017-08-21 18:41:00.866 TestForBlock[20598:453239] weakObj::: 變量值:0x608000016830, 指向?qū)ο笾担?lt;MyTestForBlock: 0x608000016830>
2017-08-21 18:41:00.866 TestForBlock[20598:453288] obj 釋放前 weakObj::: 變量值:0x608000016830, 指向?qū)ο笾担?lt;MyTestForBlock: 0x608000016830>
2017-08-21 18:41:01.866 TestForBlock[20598:453239] obj 釋放后 weakObj::: 變量值:0x0, 指向?qū)ο笾担?null)
2017-08-21 18:41:02.868 TestForBlock[20598:453288] weakObj.testText::(null)
2017-08-21 18:41:02.868 TestForBlock[20598:453288] obj 釋放后block內(nèi) weakObj::: 變量值:0x0, 指向?qū)ο笾担?null)
總結(jié):obj類對象被釋放之后,該對象的屬性為空,相對應(yīng)的弱應(yīng)用對象也會為空,則該對象屬性testText為空了,這時候如果若有對該屬性進行行為操作,就有可能出現(xiàn)crash。
查看下面代碼:
- (void)testForStrongSelf
{
MyTestForBlock *obj = [[MyTestForBlock alloc]init];
obj.testText = @"TestForBlock";
PBLog(@"obj", obj);
__weak MyTestForBlock *weakObj = obj;
PBLog(@"weakObj", weakObj);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
__strong MyTestForBlock *strongObj = weakObj;
PBLog(@"obj 釋放前 weakObj", weakObj);
PBLog(@"obj 釋放前 strongObj", strongObj);
sleep(2);
NSLog(@"weakObj.testText::%@",weakObj.testText);
NSLog(@"strongObj.testText::%@",strongObj.testText);
PBLog(@"obj 釋放后block內(nèi) weakObj", weakObj);
PBLog(@"obj 釋放后block內(nèi) strongObj", strongObj);
});
sleep(1);
obj = nil;
PBLog(@"obj 釋放后 weakObj", weakObj);
}
控制臺輸出:
2017-08-21 18:39:43.847 TestForBlock[20570:451915] obj::: 變量值:0x608000002fe0, 指向?qū)ο笾担?lt;MyTestForBlock: 0x608000002fe0>
2017-08-21 18:39:43.847 TestForBlock[20570:451915] weakObj::: 變量值:0x608000002fe0, 指向?qū)ο笾担?lt;MyTestForBlock: 0x608000002fe0>
2017-08-21 18:39:43.847 TestForBlock[20570:451975] obj 釋放前 weakObj::: 變量值:0x608000002fe0, 指向?qū)ο笾担?lt;MyTestForBlock: 0x608000002fe0>
2017-08-21 18:39:43.847 TestForBlock[20570:451975] obj 釋放前 strongObj::: 變量值:0x608000002fe0, 指向?qū)ο笾担?lt;MyTestForBlock: 0x608000002fe0>
2017-08-21 18:39:44.848 TestForBlock[20570:451915] obj 釋放后 weakObj::: 變量值:0x608000002fe0, 指向?qū)ο笾担?lt;MyTestForBlock: 0x608000002fe0>
2017-08-21 18:39:45.848 TestForBlock[20570:451975] weakObj.testText::TestForBlock
2017-08-21 18:39:45.848 TestForBlock[20570:451975] strongObj.testText::TestForBlock
2017-08-21 18:39:45.848 TestForBlock[20570:451975] obj 釋放后block內(nèi) weakObj::: 變量值:0x608000002fe0, 指向?qū)ο笾担?lt;MyTestForBlock: 0x608000002fe0>
2017-08-21 18:39:45.849 TestForBlock[20570:451975] obj 釋放后block內(nèi) strongObj::: 變量值:0x608000002fe0, 指向?qū)ο笾担?lt;MyTestForBlock: 0x608000002fe0>
總結(jié):經(jīng)過一次__strong 來強引用之后,即使在block過程中obj被釋放, weakObj和strongObj也能在本次的block中存在,這樣還是能獲取到對象的屬性。這樣我們能確定strongSelf的作用是: 避免weakSelf被釋放掉。
為了避免在 block 的執(zhí)行過程中,突然出現(xiàn) self 被釋放,導(dǎo)致出現(xiàn)若干異常!