Iphone 如何为使用回调的类创建使用块的包装器?

Iphone 如何为使用回调的类创建使用块的包装器?,iphone,objective-c,ios,objective-c-blocks,Iphone,Objective C,Ios,Objective C Blocks,我正在钻研iOS编程,我正在学习如何使用积木。我在我的项目中使用了一个糟糕的、过度设计的库,它使用一个回调方法来处理所有数据请求 @protocol SuckyClassDelegate <NSObject> -(void)returnedSuckyData:(NSMutableDictionary*)data; @end @interface SuckyClass: NSObject @property (nonatomic, weak) id<SuckyClassDele

我正在钻研iOS编程,我正在学习如何使用积木。我在我的项目中使用了一个糟糕的、过度设计的库,它使用一个回调方法来处理所有数据请求

@protocol SuckyClassDelegate <NSObject>
-(void)returnedSuckyData:(NSMutableDictionary*)data;
@end

@interface SuckyClass: NSObject
@property (nonatomic, weak) id<SuckyClassDelegate> delegate;
-(void)getSuckyData;
@end

@interface MyViewController: UIViewController <SuckyClassDelegate>
-(void)requestDataFromSuckyClass;
@end
…但我不知道如何将回调过程转换为块。你能告诉我怎么走吗

提前感谢您的智慧


顺便说一句,我只是在没有测试的情况下快速编写了代码,因此如果有任何拼写错误,我深表歉意。

诀窍是将完成块复制到一个类iVar中,您可以稍后调用它

@property (nonatomic, copy) void (^errorHandler)(NSError *);
@property (nonatomic, copy) void (^successHandler)(NSString *);
下面是一个方法,它保存两个块供以后使用,然后调用另一个类方法:

- (void)methodWithErrorHandler:(void(^)(NSError *error))errorBlock successHandler: (void(^)(NSString *data))successBlock
{
    // Copy the blocks to use later
    self.successHandler = successBlock;
    self.errorHandler = errorBlock;

    // Run code
    [self doOtherThings];
}
稍后-当我们想做的事情完成后,我们会调用另一个方法来运行这些块。在这个愚蠢的示例代码中,我们检查类属性
self.error
是否为
nil
。如果它不是
nil
,我们将该错误发送到保存的错误块。如果是
nil
,我们将
self.data
传递给成功块

- (void)finishThingsUp
{
    // Check to see if we should call the error block or the success block
    if (self.error) {
        self.errorHandler(self.error);
    } else {
        self.successHandler(self.data);
    }
    // Clean up the blocks
    self.errorHandler = nil;
    self.successHandler = nil;
}

我们可以这样使用:

typedef void (^SuccessDataBlock)(NSMutableDictionary *);
@interface SuckyClassWrapper : NSObject <SuckyClassDelegate>
    @property (nonatomic, retain) NSData *inputData;
    @property (nonatomic, copy) SuccessDataBlock completionHandler;

    + (id)requestData:(NSData *)data successBlock:(SuccessDataBlock)handler;
@end

@implementation SuckyClassWrapper

@synthesize inputData;
@synthesize completionHandler;

- (id)initWithData:(NSData *)data completionHandler:(SuccessDataBlock)handler

{
    self = [super init];
    if (self != nil)
    {
        inputData = [data retain];
        self.completionHandler = handler;
    }
    return self;
}

+ (id)requestData:(NSData *)data successBlock:(SuccessDataBlock)handler
{
    return [[[self alloc] initWithData:data completionHandler:handler] autorelease];
}

//implement SuckyClass delegate
- (void)returnedSuckyData:(NSMutableDictionary *)data
{
    self.completionHandler(data);
}

@end

迂腐地说,由于Objective-C不支持类变量,您正在使用声明的属性
self.successHandler
self.errorHandler
将块的副本分配给类实例变量。感谢您捕获@NSBumsure+1用于压缩解决方案。此外,您应该将块属性声明为副本,因此不需要显式-copy。您还应该在
finishThingsUp
末尾将两个块属性置零,以避免泄漏块中引用的对象。
typedef void (^SuccessDataBlock)(NSMutableDictionary *);
@interface SuckyClassWrapper : NSObject <SuckyClassDelegate>
    @property (nonatomic, retain) NSData *inputData;
    @property (nonatomic, copy) SuccessDataBlock completionHandler;

    + (id)requestData:(NSData *)data successBlock:(SuccessDataBlock)handler;
@end

@implementation SuckyClassWrapper

@synthesize inputData;
@synthesize completionHandler;

- (id)initWithData:(NSData *)data completionHandler:(SuccessDataBlock)handler

{
    self = [super init];
    if (self != nil)
    {
        inputData = [data retain];
        self.completionHandler = handler;
    }
    return self;
}

+ (id)requestData:(NSData *)data successBlock:(SuccessDataBlock)handler
{
    return [[[self alloc] initWithData:data completionHandler:handler] autorelease];
}

//implement SuckyClass delegate
- (void)returnedSuckyData:(NSMutableDictionary *)data
{
    self.completionHandler(data);
}

@end
SuckyClassWrapper *wrapper = [SuckyClassWrapper requestData:data successBlock:^(NSMutableDictionary *successData) {
    //your code here
}];