【问题标题】:Is it possible to subclass NSURLSessionDownloadTask to create a dedicated API for a service?是否可以继承 NSURLSessionDownloadTask 来为服务创建专用 API?
【发布时间】:2014-04-04 20:27:50
【问题描述】:

假设我想创建一种从Imgur 下载图像的简单方法。我在我的应用程序中经常这样做,所以不必为NSURLSessionDownloadTask 进行所有设置并为此用例进行配置,而是我可以使用一个可以处理大部分内容的子类那个配置。

是否可以将NSURLSession 子类化,以便与特定服务轻松交互?

假设我经常从 Imgur 链接获取图像 ID,例如 mFJlvPf。而不是设置NSURLSession,设置它的配置,创建NSURLRequest,从下载它的NSURL位置获取结果,我可以只提供图像ID并前往城镇:

ImgurDownloadTask *downloadTask = [ImgurDownloadTask taskWithImageID:@"mFJlvPf"
            progressBlock:^(CGFloat bytesWritten, CGFLoat totalBytesExpectedToBeWritten) {
            } 
            completionBlock:^(UIImage *downloadedImage) { 
            }];

[downloadTask resume];

这样的简化可能吗?如果是这样,我将如何去做?

【问题讨论】:

    标签: ios objective-c cocoa-touch ios7 nsurlsession


    【解决方案1】:

    这确实是可能的。我会这样处理问题:

    @interface ImgurClient : NSObject
    +(instancetype) sharedClient;
    -(NSURLSessionDownloadTask*)taskWithImageID:(NSString*)imageId
                                  progressBlock:(void (^)(/*TBD*/))progressBlock
                              completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler
    @end
    
    @implementation ImgurClient {
        NSURLSession* session;
    }
    
    +(instancetype) sharedClient {
        static ImgurClient* _sharedClient = nil;
        static dispatch_once_t onceToken;
    
        dispatch_once(&onceToken, ^{
            _sharedClient = [[ImgurClient alloc] init];
        });
    
        return _sharedClient;
    }
    
    -(id) init {
        self = [super init];
        if (self) {
            // Additional initialisation, setting up NSURLSession, etc
        }
    }
    
    -(NSURLSessionDownloadTask*)taskWithImageID:(NSString*)imageId
                                  progressBlock:(void (^)(/*TBD*/))progressBlock
                              completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler {
     // Build URL, store progress handler, create download task
    }
    

    也就是说,有一个 ImgurClient 对象,它是一个单例对象,当您需要执行请求时,您可以像 [[ImgurClient sharedClient] taskWithImageId:@"..." ....]; 一样使用它。

    【讨论】:

      【解决方案2】:

      您对包装此下载任务的复杂性的直觉非常好,但您可能不会继承 NSURLSessionDownloadTask,而是使用 NSURLSession 对象启动您的自定义类,因为要实现进度块,您需要实现委托方法,并且这些与任务相关的委托方法在会话的委托中调用。

      因此,将您的NSURLSession 包装在一个对象中,并将您的自定义工厂方法及其进度/完成块放在那里。如果您要提供特定于任务的进度/完成块,那么您还必须在任务标识符和这些块之间维护一些映射(例如通过NSMutableDictionary)(这样您的代表就知道要根据哪个块调用的任务标识符)。

      顺便说一句,如果您要支持后台会话,这会带来一系列完全不同的挑战(因为后台任务会持续存在于您的应用和自定义对象的标准生命周期之外)。您可能需要明确决定是否要支持后台会话(如果排除它们,您的生活会更轻松)。

      【讨论】:

        猜你喜欢
        • 2011-12-12
        • 1970-01-01
        • 2017-09-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多