【问题标题】:Subclass AFHTTPRequestOperationManager?子类 AFHTTPRequestOperationManager?
【发布时间】:2013-12-28 15:24:59
【问题描述】:

我发现自己在整个代码中使用AFHTTPRequestOperationManager 重复了很多代码,所以我正在考虑对其进行子类化,因此我可以将其设置为单例,并将所有代码放在子类中,而不是让它在我的项目中传播开来。然而,在 AFNetworking 2.0 (http://nshipster.com/afnetworking-2/) 的 NSHipster 插曲中,它说:

2.0 的主要区别在于,您实际上将直接使用此类,而不是对其进行子类化,原因在“序列化”部分中进行了说明。

由于 AFNetworking 和 NSHipster 的作者相同,我认为这是一个有效的论点。

所以我的问题是,人们是否将AFHTTPRequestOperationManager 子类化以便将大多数网络代码放在一个类中,还是我在使用框架时忽略了某些东西?

【问题讨论】:

  • 我通常将它子类化,并将这个子类用作单例。检查此处链接的报价:stackoverflow.com/a/20773611/653513 但这可能只是“一个旧习惯”。还有一点需要注意:您不必为了将其用作单例而对其进行子类化。
  • 那句话是关于AFHTTPRequestOperation,而不是AFHTTPRequestOperationManager

标签: ios objective-c afnetworking-2


【解决方案1】:

我就是这样解决的。

我创建了一个新的 MyDBClient 对象,其中 AFHTTPRequestOperationManager 是一个属性。 MyDBClient 是一个单例类。然后我从我的视图控制器调用 MyDBClient 并让它设置操作管理器并启动请求。这样做的好处还在于更容易在AFHTTPRequestOperationManager(iOS7之前)和AFHTTPPSessionManager(iOS7)之间切换。

【讨论】:

    【解决方案2】:

    我有一个连接类的对象。这会向任何可以通过[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}];
        }];
    }
    

    将接收到的数据写入 Core Data 的对象将注册 kCuriculumDataSourceFetchingSucceeded 并可以通过 notification.userInfo[@"response"] 访问接收到的响应。
    ViewController 将注册kCuriculumDataSourceFetchingSucceededkCuriculumDataSourceFetchingFailedkCuriculumDataSourceProgress

    我只实例化一个对象,我不必费心,不管它是否是单例。因此,我不必对它进行子类化或做一些相关的对象技巧来获得一个返回单例对象的方法。对从网络获取的数据感兴趣的类只会监听通知——它们不必知道获取数据的对象,也不必知道它是否是同类中唯一的。

    连接类对象本身可以注册到其他类将发布以触发新数据获取的通知。


    视图控制器可以注册通知,例如

    -(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];
    }
    

    在这种情况下,视图控制器和网络控制器导入相同的配置头文件,该文件定义了 kCuriculumDataSourceFetchingSucceeded 之类的令牌。但由于这些是普通的 NSString,即使是这种依赖也可以轻松避免。

    处理通知的视图控制器方法示例

    -(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;
    
        });
    }
    

    【讨论】:

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