【问题标题】:Objective-C: How to give a completion block to a method that uses a result from the method executionObjective-C:如何为使用方法执行结果的方法提供完成块
【发布时间】:2016-10-09 18:19:01
【问题描述】:

对象 X 需要下载图像。它具有图像的 URL(可能是网络文件)。我有一个通用的 imageHandler 类,它可以获取 URL 并获取 imageData。我想要这个方法,能够使用完成块来自定义如何处理下载的图像。

我熟悉如何使用委托模式。例如

@protocol ImageHandler: NSObject
-(void) getImageFromURL:(NSURL *)url forDelegate:(id <ImageRequestor>)delegate;
@end

@protocol ImageRequestor: NSObject
-(void) image:(UIImage *) image RetrievedForURL:(NSURL *)url withError:(NSError *)error;
@end

所以,基本上 objectX 类 getImageFromURL:delegate 方法,委托为 self。它符合 ImageRequestor 协议。

ImageHandler 对象,将 url 存储在哈希表中以委托映射。完成后,在委托上调用 image:RetrievedForURL:withError:。在这种方法中,我对图像和错误采取行动。

如何使用完成块实现相同的效果,其中我将“我想对检索到的图像做什么”作为一段代码传递。

我看到的一种方法如下。但看起来它需要 ImageHandler 方法实现调用带有特定参数的完成。这是实现这一点的公认方式(即完成处理程序依赖于接收它的方法以使用正确的参数调用它)?

@protocol ImageHandler: NSObject
-(void) getImageFromURL:(NSURL *)url withCompletionHandler:(void (^)(UIImage *image, NSError * err))completionBlock;
@end

getImageFromURL:(NSURL *)url withCompletionHandler:(void (^)(UIImage *image, NSError * err))completionBlock 的实现看起来像

getImageFromURL:(NSURL *)url withCompletionHandler:(void (^)(UIImage *image, NSError * err))completionBlock
{
 //Get UIImage from URL, store it UIIMage ObjectX
 //if error happens, store it in NSError objectY, else it is nil
 //call completion handler 
 completionBlock(<UIIMage objectX>,<NSError objectY>);
}

【问题讨论】:

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


    【解决方案1】:

    是的,您所展示的是执行此操作的典型方式。查看 Apple 自己的 API 以了解它们的操作方式相同。例如-[NSURLSession dataTaskWithURL:completionHandler:],其声明为:

    - (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url 
                            completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;
    

    【讨论】:

      【解决方案2】:

      在您的 ImageRequestor.h 文件中写入以下内容:

      #import <Foundation/Foundation.h>
      
      // Here you define your custom response block with the desired parameters
      // That in this case are UIImage and NSError
      typedef void (^ResponseBlock)(UIImage *image, NSError *error);
      
      @interface ImageRequestor : NSObject
      
      // Here you define the method that use your custom response block
      - (void)getImageFromURL:(NSURL *)url withCompletionHandler:(ResponseBlock)completionBlock;
      
      @end
      

      几乎完成了,现在打开您的 ImageRequestor.m 文件并添加以下内容:

      #import "ImageRequestor.h"
      
      @implementation ImageRequestor
      
      - (void)getImageFromURL:(NSURL *)url withCompletionHandler:(ResponseBlock)completionBlock {
        // Do all your stuff to get the image and the error
        // And set them into your completion block
        // if there is no error that should be nil
      
        // completionBlock(YourFetchedImage, YourFetchedError);
        // completionBlock(nil, YourFetchedError);
        completionBlock(YourFetchedImage, nil);
      }
      
      @end
      

      最后你可以这样称呼它:

      ImageRequestor *imageRequestor = [[ImageRequestor alloc] init];
      [imageRequestor getImageFromURL:yourURL withCompletionHandler:^(UIImage *image, NSError *error) {
        // Your implementation in here
      }];
      

      这种东西在单例类中看起来好多了:]

      希望对你有帮助, 祝你好运!!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-17
        • 1970-01-01
        • 2019-07-07
        相关资源
        最近更新 更多