簡體   English   中英

Objective-C-存儲帶有回調參數的塊

[英]Objective-C - Storing block with parameters for callback

我有一個通用例程,它帶有一些參數。 就像是:

-(id) doStuff:(int)A:(int)B:(int)C {
    //doStuff
    return object;
}

我有一個UITableViewController ,其中包含許多自定義單元格,每個單元格都有自己的ID。 當單擊“保存”時,將迭代這些單元格,並且某些單元格在保存時需要“其他行為”。

到目前為止,我已經創建了一個“回調”對象,該對象在自定義單元格中存儲了一個NSString *和一個委托。 在“保存”后,該單元格看起來是否有任何回調要應用和使用

SEL sel = NSSelectorFromString(Sel);
if([Del respondsToSelector:sel])
    [Del performSelector:sel withObject:Cell];

現在效果不錯...但是,它需要我傳遞的方法對傳遞的Cell的ID進行切換/處理,我想避免這種情況。

這就是為什么我想使用塊代替的原因,但是我真的不知道如何在變量中存儲參數化塊。

我正在嘗試做的是:

聲明功能塊doStuff

id (^doStuff) (int, int, int) = ^(int A, int B, int C) {
    //does Stuff
};

並將先前創建的塊添加為回調

[Cell addCallback:(^doStuff)(1, 2, 3)];

那一刻不能調用該塊,而應將其存儲在單元中,並且僅在適當的時候調用它。 我將如何正確處理?

非常感謝你。

編輯:我也想避免的是將塊的參數存儲在單元格中,並在調用時傳遞它們,因為這將需要我不必要地進一步專門化單元格。

聽起來您想要的是一個可以調用您的塊的塊,如下所示:

[cell addCallback:^{ doStuff(1, 2, 3); }];

但這是一個相當奇怪且令人費解的設計。 似乎只有一種方法可以編寫它,但是如果不更好地了解自己在做什么,很難給出具體的解決方案。

最直接的方法是創建一個typedef,其中包含塊參數的外觀,然后使用它來聲明新的屬性/ ivar。 以下示例代碼是從Sensible TableView框架SCCellActions類復制的:

typedef void(^SCCellAction_Block)(SCTableViewCell *cell, NSIndexPath *indexPath);

@interface SCCellActions : NSObject
...
@property (nonatomic, copy) SCCellAction_Block willDisplay;
...
@end

然后可以按如下所示設置屬性:

cellActions.willDisplay = ^(SCTableViewCell *cell, NSIndexPath *indexPath)
{
    cell.backgroundColor = [UIColor yellowColor];
};

同樣,您可以聲明一個參數,如下所示:

...
- (void)callActionBlock:(SCCellAction_Block actionBlock)
{
    if(actionBlock)
    {
        actionBlock(self.cell, self.cellIndexPath);
    }
}
...

在這種情況下,應按以下方式調用該方法:

[myObject callActionBlock:^(SCTableViewCell *cell, NSIndexPath *indexPath {cell.backgroundColor = [UIColor yellowColor];}];

該答案基於Chuck的建議,並描述了我在實現它時遇到的陷阱。

創建:

Cell = [self CreateCell];
[Cell addCallback:^{ return doStuff(Cell, 1, 2, 3, 4) } At:ON_SAVE];

doStuff是一個局部塊,在單元格之前聲明。 我無法將其直接添加到單元格中,因為我還需要對塊中調用單元格的引用。

此時的陷阱:類變量。 一個塊將只保留...或更確切地說是“復制”局部變量,而不保留類變量。 假設“ Cell”是一個類變量,並由“ CreateCell”設置,則該塊將在執行該塊時使用Cell的值。

因此,重要的是要記住聲明一個局部變量,該變量在必要時采用類變量的值。

存儲:

- (void) addCallback:(CallBlock_t)B At:(int)at {
    //Creates a Callback-Object and passes it the block and adds it to an Array.
}

- (id) initWithBlock:(CallBlock_t)B At:(int)at {
    self = [super init];
    if(self) {
        Block = [B copy];    //Yes, Copy. Not retain.
        When = at;
    }
    return self;
}

此時的陷阱:如果僅保留該塊,則調用函數中的本地塊將超出范圍,並且程序將因“錯誤訪問”而失敗。 復制可以解決此問題。

當然,一旦使用完Block(在回調類的dealloc中),您就需要釋放它,但這是已知的。

我希望這個簡短的解釋可以減輕一些人的痛苦。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM