亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用塊保留`self`循環

使用塊保留`self`循環

函數式編程 2019-09-19 08:44:26
我擔心這個問題非?;?,但我認為這與很多進入數據塊的Objective-C程序員有關。我聽到的是,由于塊捕獲作為const副本在其中引用的局部變量self,因此如果要復制該塊,則在塊內使用可能會導致保留周期。因此,我們應該使用__block強制塊直接處理self而不是復制它。__block typeof(self) bself = self;[someObject messageWithBlock:^{ [bself doSomething]; }];而不僅僅是[someObject messageWithBlock:^{ [self doSomething]; }];我想知道的是:如果這是真的,有沒有辦法可以避免丑陋(除了使用GC)?
查看完整描述

3 回答

?
德瑪西亞99

TA貢獻1770條經驗 獲得超3個贊

嚴格來說,它是一個const副本的事實與這個問題無關。塊將保留創建時捕獲的任何obj-c值。恰好,const-copy問題的解決方法與保留問題的解決方法相同; 即,使用__block變量的存儲類。

無論如何,要回答你的問題,這里沒有真正的選擇。如果你正在設計自己的基于塊的API,并且這樣做是有意義的,你可以讓塊self作為參數傳遞in 的值。不幸的是,這對大多數API來說沒有意義。

請注意,引用ivar具有完全相同的問題。如果您需要在塊中引用ivar,請使用屬性或使用bself->ivar。


附錄:編譯為ARC時,__block不再中斷保留周期。如果您正在為ARC編譯,則需要使用__weak__unsafe_unretained替代。


查看完整回答
反對 回復 2019-09-19
?
回首憶惘然

TA貢獻1847條經驗 獲得超11個贊

這可能是顯而易見的,但是self當你知道你會得到一個保留周期時,你只需要做丑陋的別名。如果塊只是一次性的東西,那么我認為你可以安全地忽略保留self。例如,當您將塊作為回調接口時,不好的情況就是如此。像這兒:

typedef void (^BufferCallback)(FullBuffer* buffer);@interface AudioProcessor : NSObject {…}@property(copy) BufferCallback bufferHandler;@end@implementation AudioProcessor- (id) init {
    …
    [self setBufferCallback:^(FullBuffer* buffer) {
        [self whatever];
    }];
    …}

這里的API沒有多大意義,但是在與超類通信時也是有意義的。我們保留緩沖區處理程序,緩沖區處理程序保留了我們。比較這樣的事情:

typedef void (^Callback)(void);@interface VideoEncoder : NSObject {…}- (void) encodeVideoAndCall: (Callback) block;@end@interface Foo : NSObject {…}@property(retain) VideoEncoder *encoder;@end@implementation Foo- (void) somewhere {
    [encoder encodeVideoAndCall:^{
        [self doSomething];
    }];}

在這些情況下,我不做self別名。你確實得到一個保留周期,但是操作是短暫的,并且塊最終會從內存中斷開,從而打破周期。但是我對塊的體驗非常小self,從長遠來看,混疊可能是最佳實踐。


查看完整回答
反對 回復 2019-09-19
  • 3 回答
  • 0 關注
  • 584 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號