3 回答

TA貢獻(xiàn)1770條經(jīng)驗(yàn) 獲得超3個(gè)贊
嚴(yán)格來(lái)說(shuō),它是一個(gè)const副本的事實(shí)與這個(gè)問(wèn)題無(wú)關(guān)。塊將保留創(chuàng)建時(shí)捕獲的任何obj-c值。恰好,const-copy問(wèn)題的解決方法與保留問(wèn)題的解決方法相同; 即,使用__block
變量的存儲(chǔ)類(lèi)。
無(wú)論如何,要回答你的問(wèn)題,這里沒(méi)有真正的選擇。如果你正在設(shè)計(jì)自己的基于塊的API,并且這樣做是有意義的,你可以讓塊self
作為參數(shù)傳遞in 的值。不幸的是,這對(duì)大多數(shù)API來(lái)說(shuō)沒(méi)有意義。
請(qǐng)注意,引用ivar具有完全相同的問(wèn)題。如果您需要在塊中引用ivar,請(qǐng)使用屬性或使用bself->ivar
。
附錄:編譯為ARC時(shí),__block
不再中斷保留周期。如果您正在為ARC編譯,則需要使用__weak
或__unsafe_unretained
替代。

TA貢獻(xiàn)1847條經(jīng)驗(yàn) 獲得超11個(gè)贊
這可能是顯而易見(jiàn)的,但是self
當(dāng)你知道你會(huì)得到一個(gè)保留周期時(shí),你只需要做丑陋的別名。如果塊只是一次性的東西,那么我認(rèn)為你可以安全地忽略保留self
。例如,當(dāng)您將塊作為回調(diào)接口時(shí),不好的情況就是如此。像這兒:
typedef void (^BufferCallback)(FullBuffer* buffer);@interface AudioProcessor : NSObject {…}@property(copy) BufferCallback bufferHandler;@end@implementation AudioProcessor- (id) init { … [self setBufferCallback:^(FullBuffer* buffer) { [self whatever]; }]; …}
這里的API沒(méi)有多大意義,但是在與超類(lèi)通信時(shí)也是有意義的。我們保留緩沖區(qū)處理程序,緩沖區(qū)處理程序保留了我們。比較這樣的事情:
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
別名。你確實(shí)得到一個(gè)保留周期,但是操作是短暫的,并且塊最終會(huì)從內(nèi)存中斷開(kāi),從而打破周期。但是我對(duì)塊的體驗(yàn)非常小self
,從長(zhǎng)遠(yuǎn)來(lái)看,混疊可能是最佳實(shí)踐。
- 3 回答
- 0 關(guān)注
- 574 瀏覽
添加回答
舉報(bào)