下载,保存和重新加载UITableView会阻止UI

时间:2014-02-26 19:45:28

标签: ios objective-c uitableview core-data grand-central-dispatch

我的应用中有collectData方法,这是 View Controller 中最重要的部分。在那个方法中,我做了几个重要的事情(下载,解析,保存到持久存储),所以你可以更容易看看:

-(void)collectData
{
    // Downloading all groups and saving them to Core Data
    [[AFHTTPRequestOperationManager manager] GET:ALL_GROUPS parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSMutableDictionary* groups = [NSMutableDictionary new];
        NSMutableArray* newIds = [NSMutableArray new];
        NSError *error;

        // Saving everything from response to MOC
        for (id group in responseObject) {
            Group *groupEntity = [NSEntityDescription insertNewObjectForEntityForName:@"Group" inManagedObjectContext:self.moc];

            groupEntity.name = [group valueForKey:@"name"];
            groupEntity.cashID = [group valueForKey:@"id"];
            groupEntity.caseInsensitiveName = [[group valueForKey:@"name"] lowercaseString];
            groupEntity.selected = @NO;

            // Filling up helping variables
            groups[groupEntity.cashID] = groupEntity;
            [newIds addObject:groupEntity.cashID];
        }

        // Fetching existing groups from Persistant store
        NSFetchRequest* r = [NSFetchRequest fetchRequestWithEntityName:@"Group"];
        [r setIncludesPendingChanges:NO];
        r.predicate = [NSPredicate predicateWithFormat:@"cashID IN %@",newIds];
        NSArray *existingGroups = [self.moc executeFetchRequest:r error:&error];

        // Deleting groups which already are in database
        for (Group* g in existingGroups) {
            Group* newGroup = groups[g.cashID];
            g.name = [newGroup valueForKey:@"name"];
            g.cashID = [newGroup valueForKey:@"cashID"];
            g.caseInsensitiveName = [[newGroup valueForKey:@"name"] lowercaseString];
            [self.moc deleteObject:newGroup];
        }

        // Saving Entity modification date and setting it to pull to refresh
        [self saveModificationDate:[NSDate date] forEntityNamed:@"Group"];
        [self.pullToRefreshView.contentView setLastUpdatedAt:[self getModificationDateForEntityNamed:@"Group"]
                                       withPullToRefreshView:self.pullToRefreshView];

        // Save groups to presistant store
        if (![self.moc save:&error]) {
            NSLog(@"Couldn't save: %@", [error localizedDescription]);
        }

        [[self fetchedResultsController] performFetch:&error];
        [self.pullToRefreshView finishLoading];
        [self.tableView reloadData];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        // Show alert with info about internet connection
        [self.pullToRefreshView finishLoading];
        UIAlertView *internetAlert = [[UIAlertView alloc] initWithTitle:@"Ups!" message:@"Wygląda na to, że nie masz połączenia z internetem" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
        [internetAlert show];
    }];
}

因此,当我开始收集数据(首次运行或推送刷新)时,此方法会阻止UI。 我想避免这种情况,但当我将success块放入另一个dispatch_async并仅返回[self.tableView reloadData]的主队列时,我遇到了保存到持久存储或索引错误的问题。

如何在后台执行此操作并让用户界面响应用户界面?

2 个答案:

答案 0 :(得分:0)

只是一个想法,请尝试使用dispatch_sync。在这里查看this explanation,其中日志结果类似于您的需要。在同步阻止之后放置[yourTableView reloadData]

希望它有所帮助!

答案 1 :(得分:0)

似乎AFNetwork调用不是异步,所以只需尝试通过performselector调用你的方法。