我擔心這個問題非?;?,但我認為這與很多進入數據塊的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
替代。

回首憶惘然
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
,從長遠來看,混疊可能是最佳實踐。
- 3 回答
- 0 關注
- 584 瀏覽
添加回答
舉報
0/150
提交
取消