从委托方法调用完成块

4

很难解释,但基本上我正在尝试的是在委托方法中从一个基于块的方法调用完成处理程序。

我有一个调用上传函数的方法。

[[UploadManager sharedManager] uploadFile:@"/Path/To/Image.png" success:^(NSDictionary *response) {
    NSLog(@"Uploaded");
}];

在UpLoad管理器内,该方法执行上传文件的所有必要操作。

有一个代理方法,我想从中调用成功块。

- (void)fileDidUploadAndReceiveData:(NSData *)data {
    NSDictionary *response = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&parseError];
    // Call the completion method
    success(response);
}

success被定义在uploadFile方法中,我该如何调用这个完成处理器?

我这是深夜写的,如果有不清楚的地方请告诉我。

谢谢。


“fileDidUploadAndReceiveData” 位于哪里?在委托类中吗?如果是的话,我相信您的UploadManager中将有一个委托属性。那么为什么不直接调用 [self.delegate fileDidUploadAndReceiveData:dataYouWantToSend]; 呢? - nsuinteger
5个回答

12

声明一个属性,它是该块的副本:

@property(nonatomic, copy) void (^completionBlock)(NSDictionary *);

在uploadFile中进行赋值:

- (void)uploadFile:(NSString *)url success:(void (^)(NSDictionary *))completionBlock {
    self.completionBlock = completionBlock;
    // ...
然后在需要的时候调用它:
if (self.completionBlock) self.completionBlock(someDictionary);
self.completionBlock = nil;  // see below
记住,如果你不再需要这个块(因为下载已经完成),那么最好的做法是将你复制出来的块置空。这样,如果调用者在块内引用下载管理器,你会帮助他打破保留循环(块会保留下载管理器,而下载管理器又会保留该块)。

1
在尝试调用块之前最好确保它不为 nil - rmaddy

0
在你的UploadManager类中创建一个实例变量来存储成功回调块。在uploadFile:success:方法中设置这个实例变量。然后在fileDidUploadAndReceiveData:方法中使用这个实例变量来调用该块。

0
在UploadManager中添加属性@property (nonatomic, copy) void (^tempSuccess)(NSDictionary * response); 在uploadFile方法中赋值。
self.tempSuccess = success;

最后

- (void)fileDidUploadAndReceiveData:(NSData *)data {
    NSDictionary *response = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&parseError];
    // Call the completion method
    self.tempSuccess(response);
}

希望这能有所帮助!

你应该将代码块属性声明为“copy”,而不是“strong”。 - nsuinteger
更正。是的,应该复制-如苹果文档建议。 - jnix

0

除了我上面的评论,这是我通常处理块操作的方式。

在你的UploadManager.h文件中定义一个类型

//// .h文件

typedef void (^ActionNameBlock)(id responseObject);


- (void)setAction:(ActionNameBlock)actionBlock;

在你的UploadManager.m文件中
//// .m文件
@property (nonatomic, copy) ActionNameBlock action;

- setAction:(ActionNameBlock)_action
{
self.action = _action;
}


// now in your block operation code 

[[UploadManager sharedManager] uploadFile:@"/Path/To/Image.png" success:^(NSDictionary *response)
 {
    NSLog(@"Uploaded");
if (self.action) { self.action(response); }
}];

0

fileDidUploadAndReceiveData 是在 UploadManager 中定义的吗?

如果是,那么您可以只存储成功块的副本,并按照您编写的方式调用它。

在您的 UploadManager 头文件中添加一个复制块属性:

typedef void (^OnUploadFileSuccesBlock)(NSDictionary *response);

@interface UploadManager : NSObject

@property (nonatomic, copy) OnUploadFileSuccesBlock uploadFileSucces;

在uploadFile方法中保留成功块的一个副本:
- (void) uploadFile:(NSString*)path success:(OnUploadFileSuccesBlock)block {
  self.uploadFileSucces = block
  ...
}

在你的代理方法中,你可以直接调用它:

- (void)fileDidUploadAndReceiveData:(NSData *)data {
    NSDictionary *response = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&parseError];
    // Call the completion method
    self.uploadFileSucces(response);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接