一个接一个地执行任务

时间:2015-07-21 20:35:23

标签: ios objective-c json multithreading grand-central-dispatch

最近我开始为iOS开发并面临一些问题,这对你来说可能是显而易见的,但我自己无法解决这个问题。 我尝试做的是使用GCD提供的多线程执行另一个任务。

这是我获取JSON的代码(用singleton放在类中) CategoriesStore

- (instancetype)initPrivate {
    self = [super init];

    if (self) {
        [self sessionConf];

        NSURLSessionDataTask *getCategories =
        [self.session dataTaskWithURL:categoriesURL
                    completionHandler:^(NSData *data,
                                        NSURLResponse *response,
                                        NSError *error) {
                        if (error) {
                            NSLog(@"error - %@",error.localizedDescription);
                        }

                        NSHTTPURLResponse *httpResp = (NSHTTPURLResponse *) response;

                        if (httpResp.statusCode == 200) {
                            NSError *jsonError;

                            NSArray *json =
                            [NSJSONSerialization JSONObjectWithData:data
                                                            options:NSJSONReadingMutableContainers
                                                              error:&jsonError];
                            if (!jsonError) {
                                _allCategories = json;
                                NSLog(@"allcategories - %@",_allCategories);
                            }
                        }
        }];

        [getCategories resume];
    }

    return self;
}

然后在ViewController中执行

- (void)fetchCategories {
    NSLog(@"before");

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
            CategoriesStore *categories = [CategoriesStore sharedStore];
        dispatch_async(dispatch_get_main_queue(), ^(void) {
            _allDirectories = categories.allCategories;
            [self.tableView reloadData];
            NSLog(@"after");
        });
    });
}

-fetchCategories在viewDidAppear中执行。结果通常是之前,之后,然后 JSON 。显然我想要的是之前,json之后

我也尝试使用dispatch_group_notify来做这件事,但没有工作。

我怎样才能让它发挥作用?为什么它不等待第一个任务完成? 感谢您的帮助! 此致,阿德里安。

3 个答案:

答案 0 :(得分:0)

您必须等待重新加载数据,以便您可以执行此类操作,如果您不想等待整个块,则另一个选项是仅使用自定义NSLock

dispatch_sync(dispatch_get_main_queue(), {
    _allDirectories = categories.allCategories;
    [self.tableView reloadData];
}
NSLog(@"after");

答案 1 :(得分:0)

我建议在CategoriesStore中定义一个专用方法,从远程服务器获取数据并将回调作为参数:

- (void)fetchDataWithCallback:(void(^)(NSArray *allCategories, NSError* error))callback
{

    NSURLSessionDataTask *getCategories =
        [self.session dataTaskWithURL:categoriesURL
                    completionHandler:^(NSData *data,
                                        NSURLResponse *response,
                                        NSError *error) {
                        if (error) {
                            NSLog(@"error - %@",error.localizedDescription);
                            callback(nil, error);
                            return;
                        }

                        NSError *jsonError = nil;

                        NSArray *json =
                        [NSJSONSerialization JSONObjectWithData:data
                                                        options:NSJSONReadingMutableContainers
                                                          error:&jsonError];
                        if (!jsonError) {
                            _allCategories = json;
                            NSLog(@"allcategories - %@",_allCategories);
                            callback(_allCategories, nil);
                        } else {
                            callback(nil, jsonError);
                        }
        }];

        [getCategories resume];
}

您可以在ViewController

中使用它
- (void)fetchCategories {
    [[CategoriesStore sharedStore] fetchDataWithCallback:^(NSArray *allCategories, NSError* error) {
        if (error) {
            // handle error here
        } else {
            _allDirectories = allCategories;
            [self.tableView reloadData];
        }
    }]
}

通过这种方式,您将在数据加载后重新加载表格视图。解析。

答案 2 :(得分:0)

我使用@ sgl0v建议的方法,虽然它不是我预期的解决方案。 另一种方法是使用通知中心并监听事件发生。