或者是否必须编写方法来接受块?换句话说,如果我们不控制定义方法的代码,我们是否可以使用代理,如果它是如何定义的,或者是否有办法传递两个匿名期望委托的方法调用中的函数(块)?
答案 0 :(得分:6)
从技术上讲,答案是否定的,如果某些图书馆或班级与代表合作,可能有充分的理由,聪明而容易的事情就是使用它们。
如果出于某种原因,您真的对使用块感兴趣,因为它对您的问题域更自然,您可以实现一个包装器。
前方超级奇怪的例子。
例如,在UITableViewDataSource
委托中,您有一个方法来获取每个部分中的行数:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
为了使用它,您必须将表dataSource
属性设置为实现该方法的某个对象。通常的东西。
您可以创建一个数据源包装器来实现原始协议和您定义的新协议,以使用您想要的块接口。
typedef NSUInteger (^RowsCounterBlock)(NSInteger section);
@protocol RowsCounter
- (void)tableViewController:(id)controller countRowsWithBlock:(RowsCounterBlock)block;
@end
// we implement both the original protocol and our block based protocol
@interface ComplexDataSource : NSObject <UITableViewDataSource, RowsCounter>
{
@property(strong) RowsCounterBlock counterBlock;
}
// save a block that knows how to count rows
- (void)tableViewController:(id)controller countRowsWithBlock:(RowsCounterBlock)block
{
controller.dataSource = self;
self.counterBlock = block;
}
// use the saved block to implement the method defined in the original delegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (!self.counterBlock) return 0;
return self.counterBlock(section);
}
@end
然后在你的表控制器中:
self.source = [ComplexDataSource new]; // save the data source in a property
[self.source tableViewController:self
countRowsWithBlock:^NSUInteger(NSInteger section) {
// this will be called each time the table view needs to ask
// for the number of rows via the proxy delegate
<#do your magic#>
return <#rows#>;
}]
答案仍然是否定的,因为您正在使用原始委托......但是在幕后,您的主要界面现在是基于块的。
答案 1 :(得分:1)
简短的问题是否定的,如果定义方法来获取委托参数,如果你想使用一个块,那你就不走运了。
但是,正如其他人所说,有时委托模式比块更好,这一切都归结为用例。也许如果API设计者选择了委托而不是块,那么就有一个原因。
IMHO块在成功或失败回调时最有用,但在很多其他情况下,委托仍然更好(但是,我也喜欢使用匿名类,Java风格:)但是&# 39; s只是因为有时候我们会懒惰)
答案 2 :(得分:0)
首先,委托在许多情况下比使用闭包更好。在其他情况下,闭合更好。所以在一开始就应该问:为什么?
但是:定义调用闭包的委托方法有什么问题?