iOS / Objective-C:如何混合委托和块?

时间:2013-01-30 16:24:51

标签: ios objective-c delegates objective-c-blocks

我有两节课。 Delegator使用委托发送结果。 Blocker在静态方法中使用块。

如果不更改Delegator,我如何优雅且轻松地实施methodWithBlock,以便使用methodWithDelegate生成的结果调用块?

委托者:

@class Delegator;

@protocol Delegate <NSObject>
- (void)delegator:(Delegator *)sender producedResult:(int)result;
@end

@interface Delegator : NSObject
@property (weak, nonatomic) id <Delegate> delegate;
- (void)methodWithDelegate;
@end

@implementation Delegator
- (void)methodWithDelegate
{
    // Some asynchronous computation resulting in
    [self.delegate delegator:self producedResult:42];
}
@end

阻断剂:

@interface Blocker : NSObject
+ (void)methodWithBlock:(void(^)(int result))block;
@end

@implementation Blocker
+ (void)methodWithBlock:(void(^)(int result))block
{
    // How to call Delegator's methodWithDelegate and return
    // the result using block ?
    ...
}
@end

探索解决方案:

  • Delegator包装到新的类或类别中,并创建一个返回块的方法,如this answer中所述。这些解决方案有效,但过于复杂和耗时。

  • 使Blocker符合协议Delegate并将块保留在属性中,在方法methodWithBlock中实例化它,并在调用委托方法时调用块。这不起作用,因为没有强大的指针指向这个新实例并且它被破坏了。

  • 在前面的解决方案中,为避免因缺少强指针而丢失实例,请保留当前Blocker实例的静态数组,并在委托回调方法中删除它们。同样,这个解决方案有效,但太复杂了。

2 个答案:

答案 0 :(得分:0)

使用可观察的属性来传达结果,而不是委托和阻止属性。它更干净(也更容易),因为工作对象不必担心谁可能正在观看它。观看对象不必担心符合任何特殊协议。

答案 1 :(得分:0)

优雅而简单的解决方案是只为您的Delegator添加基于块的方法(例如通过类别)。我知道你说你不能这样做,但我们不得不承认,任何其他基于块的解决方案,你正在创建新的类来产生你想要的效果,都无法进行优雅测试。

话虽如此,如果你迫切需要基于块的方法并且无法扩展Delegator,那么我将倾向于选项2,除了制作那些类方法,使它们成为实例方法,并且{{1} 1}}实例化Blocker并定义包装器方法,以便使用Delegator的类现在可以使用Delegator,但使用Blocker块而不是委托回调。以前实例化completion的类现在可以实例化Delegator