我的应用中有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]
的主队列时,我遇到了保存到持久存储或索引错误的问题。
如何在后台执行此操作并让用户界面响应用户界面?
答案 0 :(得分:0)
只是一个想法,请尝试使用dispatch_sync
。在这里查看this explanation,其中日志结果类似于您的需要。在同步阻止之后放置[yourTableView reloadData]
。
希望它有所帮助!
答案 1 :(得分:0)
似乎AFNetwork调用不是异步,所以只需尝试通过performselector调用你的方法。