Subclass AFHTTPRequestOperationManager?

我是研究僧i 提交于 2019-11-30 20:55:48

This is how I solved it.

I created a new MyDBClient object, of which the AFHTTPRequestOperationManager is a property. MyDBClient is a singleton class. I then call my MyDBClient from my view controllers and let that setup the operation manager and start the request. Advantage of this is also that it is easier to switch between AFHTTPRequestOperationManager (pre iOS7) and AFHTTPPSessionManager (iOS7).

I have an object of a connection class. This broadcasts different notifications to any object can register for via [NSNotificationCenter defaultCenter].

-(void) requestData
{
    [[NSNotificationCenter defaultCenter] postNotificationName:kCuriculumDataSourceFetchingStarted object:nil];

    [_sessionManager setDataTaskDidReceiveDataBlock:^(NSURLSession *session,
                                                      NSURLSessionDataTask *dataTask,
                                                      NSData *data)
     {
        if (dataTask.countOfBytesExpectedToReceive == NSURLSessionTransferSizeUnknown)
            return;

        NSUInteger code = [(NSHTTPURLResponse *)dataTask.response statusCode];
        if (!(code> 199 && code < 400))
            return;

        long long  bytesReceived = [dataTask countOfBytesReceived];
        long long  bytesTotal = [dataTask countOfBytesExpectedToReceive];

        NSDictionary *progress = @{@"bytesReceived": @(bytesReceived),
                                   @"bytesTotal":    @(bytesTotal)};

        [[NSNotificationCenter defaultCenter] postNotificationName:kCuriculumDataSourceProgress object:nil userInfo:progress];
    }];



    [self.sessionManager GET:@"recipient/"
                  parameters:nil
                     success:^(NSURLSessionDataTask *task, id responseObject)
    {
        [[NSNotificationCenter defaultCenter] postNotificationName:kCuriculumDataSourceFetchingSucceeded
                                                            object:nil
                                                          userInfo:@{@"response": responseObject}];
    }
                     failure:^(NSURLSessionDataTask *task, NSError *error)
    {

        NSUInteger code = [(NSHTTPURLResponse *)task.response statusCode];
        NSString *msg;
        switch (code) {
            case kCuriculumDataSourceFetchErrorAPIKeyNotFound:  msg = @"Api Key not found or revoked"; break;
            case kCuriculumDataSourceFetchErrorServerDown:      msg = @"Server Down"; break;
            default:    msg = [error localizedDescription]; break;
        }


        [[NSNotificationCenter defaultCenter] postNotificationName:kCuriculumDataSourceFetchingFailed
                                                            object:nil
                                                          userInfo:@{@"error": msg}];
    }];
}

An object that would write the received data to Core Data would register for kCuriculumDataSourceFetchingSucceeded and can access the received response via notification.userInfo[@"response"].
The ViewController would register for kCuriculumDataSourceFetchingSucceeded, kCuriculumDataSourceFetchingFailed and kCuriculumDataSourceProgress.

I only instantiate one object, I don't have to bother, if it is an singleton or not. And therefor I don't have to subclass it or do some associated object tricks to get an method that would return the singleton object. Classes interested in the data fetched from network will just listen for the notification — they don't have to know the object that fetched the data and they don't have to know if it is the only of its kind.

The connection class object itself can register to a notification that other classes would post to trigger a new data fetch.


A view controller could register for notifications like

-(void)configure
{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(fetchingStarted:) name:kCuriculumDataSourceFetchingStarted object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(fetchingSucceeded:) name:kCuriculumDataSourceFetchingSucceeded object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(fetchingFailed:) name:kCuriculumDataSourceFetchingFailed object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dataSourceProgress:) name:kCuriculumDataSourceProgress object:nil];
}

In this case the view controller and the network controller import the same configuration header file that defines the tokens like kCuriculumDataSourceFetchingSucceeded. But as these are plain NSStrings, even this dependency can be avoided easily.

An example for a view controllers method that will handle a notification

-(void)dataSourceProgress:(NSNotification *)notification
{
    float bytesReceived = (float)[notification.userInfo[@"bytesReceived"] longLongValue];
    float bytesTotal = (float)[notification.userInfo[@"bytesTotal"] longLongValue];

    float progress = bytesReceived / bytesTotal;

    dispatch_async(dispatch_get_main_queue(), ^{
        self.progressView.progress = progress;
        self.imgView.layer.mask = self.progressView.layer;

    });
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!