如何从两个不同的控制器同时管理两个AFNetworking操作

时间:2013-06-03 23:49:08

标签: ios afnetworking

我从两个视图控制器运行两个AFJSONRequestOperation,它们被一个接一个地调用:

viewcontroller1:

AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON){

//
}failure:^(NSURLRequest *request, NSHTTPURLResponse *response,NSError *error, id JSON){
//
}];
[operation start];
[SVProgressHUD showWithStatus:@"Searching for products, please wait.."];

viewcontroller2:

AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON){

//
}failure:^(NSURLRequest *request, NSHTTPURLResponse *response,NSError *error, id JSON){
//
}];
[operation start];
[SVProgressHUD showWithStatus:@"Loading categories.."];

问题是显示的状态仅适用于第二个操作:Loading categories..尽管他们完成了网络连接并获得了JSON结果。

似乎我不能使用NSOperationQueue,因为这两个操作都在分开的控制器中。那么如何确保一个人等到第一个完成后向用户显示两个状态消息?

1 个答案:

答案 0 :(得分:1)

有几点想法:

  1. 如果你真的想要,你肯定可以为这两个操作使用相同的操作队列。您可以将操作队列从第一个控制器传递到第二个控制器。或者你可以为你的队列设置一个单例类。

  2. 但这是一个有争议的问题,因为您还可以在完成第一个操作时建立第二个操作的依赖关系,而无需使用共享队列。您只需要将第一个请求的NSOperation传递给第二个控制器,然后将第一个操作设置为第二个操作dependency

  3. 然而,这也是一个有争议的问题,因为如果你不需要,你为什么要引入串行操作的人为约束。如果同时运行它们而不是按顺序运行,则两个网络操作可以大大加快运行速度为了简化您更新HUD的工作量,以较慢的性能惩罚用户似乎是一种耻辱。

  4. 在我看来,正确的解决方案是支持并发操作并适当更新HUD。也许维护一组可变的状态消息,您可以在列表中添加和删除它们。

  5. 也许是这样的:

    @interface HUDStatus ()
    @property (nonatomic, strong) NSMutableArray *statusMessages;
    @end
    
    @implementation HUDStatus
    
    + (instancetype)sharedHudManager
    {
        static id sharedMyManager = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            sharedMyManager = [[self alloc] init];
        });
        return sharedMyManager;
    }
    
    - (id)init
    {
        self = [super init];
        if (self) {
            _statusMessages = [[NSMutableArray alloc] init];
        }
        return self;
    }
    
    - (void)addMessage:(NSString *)message
    {
        [self.statusMessages addObject:message];
        [SVProgressHUD showWithStatus:message];
    }
    
    - (void)removeMessage:(NSString *)message
    {
        __block BOOL didFindMessage = NO;
    
        // remove the message (not sure which one it is, so we'll look through all of them
    
        [self.statusMessages enumerateObjectsWithOptions:0 usingBlock:^(NSString *oldMessage, NSUInteger idx, BOOL *stop) {
            if ([oldMessage isEqualToString:message])
            {
                [self.statusMessages removeObjectAtIndex:idx];
                didFindMessage = YES;
                *stop = YES;
            }
        }];
    
        if (!didFindMessage)
            NSLog(@"%s: Trying to remove '%@' but it was not found in %@", __FUNCTION__, message, self.statusMessages);
    
        // if, having removed
        if ([self.statusMessages count] > 0)
            [SVProgressHUD showWithStatus:[self.statusMessages lastObject]];
        else
            [SVProgressHUD dismiss];   // I don't know this class, so I don't know what the name of the method to dismiss the HUD
    }
    
    @end