2014-11-06 41 views
5

我正在比較Objective-C中委託與塊的內存佔用情況,以解決同樣的問題。例如,有一個工人階級誰做了一些工作:ObjC:委託vs塊的內存使用情況?

// delegate 
@protocol WorkerDelegate : NSObject 
- (void)workHasBeenDone; 
@end 

// block 
typedef void (^WorkerBlock)(); 

@interface Worker : NSObject 

@property (nonatomic, weak) id<WorkerDelegate> delegate; 

@property (nonatomic, copy) WorkerBlock block; 

- (void)doTheWork; 

@end 

的代碼是不言自明,爲了知道什麼時候工作已經完成,我可以使用委託或塊:

@implementation MyObject 

- (void)workHasBeenDone 
{ 
    [self doCleanUp]; 
} 

- (void)entryMethod 
{ 
    Worker *worker = [Worker new]; 
    worker.delegate = self; 
    // or: 
    worker.block = ^{[self doCleanUp];}; 
    [worker doTheWork]; 
} 

@end 

據我所知,在上面的代碼中,self作爲委託,在內存中; block被複制到堆上,但我不確定,哪個具有更好的內存佔用?

現在我需要的工人數量:

Worker *workerA = ... // created and set delegate OR block for completion notification 
Worker *workerB = ... // created and set delegate OR block for completion notification 
Worker *workerC = ... // created and set delegate OR block for completion notification 
... 

NSDictionary *workers = @{ 
    "jobA": workerA, 
    "jobB": workerB, 
    ... 
}; 

在這種情況下,塊似乎是清潔的,但儘管如此,它有更好的,相同或更糟糕的內存佔用?

非常感謝!

+1

要知道的唯一方法就是嘗試它並進行測量。具體細節取決於實施每種方法的細節來做你想做的事 – uchuugaka 2014-11-07 00:04:22

回答

9

塊是一個ObjC對象,所以它具有相同的內存使用情況。你在正確的道路上思考多個Worker s - 如果你想對所有人做同樣的清理,會發生什麼?

與代理人:

workerA.delegate = workerB.delegate = workerC.delegate = self; 

//... 

- (void)workHasBeenDoneWithWorker:(Worker *)worker { 
    //... 
} 

在這裏你會得到相同的對象具有三個弱引用,所以不需要額外的存儲或所有權的要求。同樣workHasBeenDoneWithWorker:方法被調用三次。 (注意我稍微改了一下 - 對於一個委託方法來說,知道是誰調用它是很好的,正是出於這個原因:一個對象可以是多個其他對象的委託,並且它可能想知道委派了哪些對象的工作。)

現在,隨着塊:

workerA.block = workerB.block = workerC.block = ^{ [self doCleanUp]; }; 

因爲你的塊聲明@property (copy),這可以讓你的塊的三個副本。即使它的源代碼是相同的,每個內部和捕獲狀態也會不同。此外,塊沒有辦法(如聲明)知道它正在做什麼工作......並且如果您添加了一個參數給引用其所屬的塊的參數,則必須注意參考週期。內存使用差異是微不足道的,但API體系結構差異更爲顯着。

在一般情況下,代表工作以及時:

  • 多個委託對象可以共享相同的委託
  • 相同的委託方法可能會被調用多次對同一委託對象

而且(完成處理程序樣式)塊可以很好地工作:

  • 工作將一次完成,該塊將被調用一次,然後該塊將被丟棄
  • 完成的任務是如此緊密聯繫在一起的安裝任務,一個塊來捕捉周圍的狀態的能力是有價值的
+0

好的,徹底的答案(投票)。不過,有一個狡猾的說法。作爲協議設計的一部分,您的委託設計專門將委派給委託的事情傳遞給委託。代表模式不會「免費」。同樣,您可以設計一個完成處理程序樣式塊,它傳入正在執行完成代碼的對象。要說「......沒有辦法(如聲明的)讓這個區塊知道它在做什麼工作......」是特定實現的缺點,而不是設計模式的限制。 – 2014-11-07 02:34:11

+0

因此「聲明」限定符。另外請注意,如果您更改了塊簽名以將委託對象作爲參數傳遞,則必須注意參考週期。 – rickster 2014-11-07 04:46:21

+0

「即使它的源代碼是相同的,每個內部和捕獲狀態也會不同。」他們爲什麼會不一樣?你只評估一個塊文字一次;國家應該是一樣的。 – newacct 2014-11-08 02:11:48

0

塊回調模式使您可以比委託模式更好地控制內存管理關係。

對於委託模式,無論委託鏈接是強還是弱參考,都是在進行委託的類的聲明中確定的(無論該屬性是否宣佈爲strongweak)。它通常是weak。作爲委託對象(父對象)的對象無法控制它的意圖。

Parent object <----weak---- Delegator 

與塊回調模式,類做委派具有很強的參考塊,但是塊,這是由父對象提供,可以有一個強或弱參考父對象,這有效地決定了委託人與父對象之間的強弱關係。它可以這樣做,因爲通常在父對象代碼中創建的塊可以選擇強烈(直接)或弱(通過使用weakSelf變量)捕獲self(父對象)。

因此,使用此委託類的父對象可以根據特定用例的設計要求控制鏈接是強還是弱。

Parent object <----strong/weak---- block <----strong---- Delegator