带有 fetchedResultsController 的 Tableview 在应用重启或视图重新加载之前不会更新新内容
Tableview with fetchedResultsController not updating new content until app restart or view gets reloaded
我的表视图不会被 nsfetchedresultscontroller 中拉取的数据填充,直到应用程序重新启动或我转到另一个视图控制器并返回。我以前从来没有遇到过这个问题,很奇怪。
代码:
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 60, 0);
[super viewDidLoad];
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
// Update to handle the error appropriately.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
exit(-1); // Fail
}
UIRefreshControl *refresh = [[UIRefreshControl alloc] init];
[refresh addTarget:self
action:@selector(refresh)
forControlEvents:UIControlEventValueChanged];
self.refreshControl = refresh;
UITableViewController *tableVC = [[UITableViewController alloc]initWithStyle:UITableViewStylePlain];
[tableVC setTableView:self.tableView];
tableVC.refreshControl = self.refreshControl;
[self.tableView setContentOffset:CGPointMake(0.0f, -60.0f)
animated:YES];
[self getPosts];
// Do any additional setup after loading the view.
}
getPosts 获取 tableview 的所有帖子并将它们保存到 coredata。
-(void)getPosts
{
[self.refreshControl beginRefreshing];
[self.postsController getPostsFeedWithCompletion:^(BOOL complete, NSArray *posts) {
[self.refreshControl endRefreshing];
} failure:^(NSString *message) {
[self.refreshControl endRefreshing];
ALAlertBanner *alert = [ALAlertBanner alertBannerForView:self.view
style:ALAlertBannerStyleFailure
position:ALAlertBannerPositionTop
title:@"Error"
subtitle:@"Error retrieving posts, please try again."];
[alert show];
}];
}
getPostsFeedWithCompletion 方法:
-(void)getPostsFeedWithCompletion:(void (^)(BOOL complete, NSArray *posts))complete
failure:(void (^)(NSString *message))failure
{
[[APIManager sharedManager] getPath:@"posts/feed"
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
DLog(@"response: %@", responseObject);
NSArray __block *posts;
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext){
posts = [self createPosts:responseObject[@"posts"] inContext:localContext];
} completion:^(BOOL success, NSError *error) {
if(complete){
complete(YES, posts);
}
}];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
DLog(@"error: %@", error);
if(failure){
failure(@"Error retrieving posts");
}
}];
}
这里是 nsfetchedresultscontroller 实例化
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSManagedObjectContext *context = [NSManagedObjectContext MR_contextForCurrentThread];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"Post" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *following = [[SessionManager getInstance].currentLoggedInUser.follows allObjects];
NSMutableArray *predicateArray = [NSMutableArray array];
NSDate *now = [NSDate date];
[predicateArray addObject:[NSPredicate predicateWithFormat:@"account IN %@", following]];
[predicateArray addObject:[NSPredicate predicateWithFormat:@"expiration > %@", now]];
NSCompoundPredicate *filterPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicateArray];
[fetchRequest setPredicate:filterPredicate];
[fetchRequest setFetchBatchSize:20];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:@"expiration" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:context
sectionNameKeyPath:nil
cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
这是来自 MagicalRecord 保存的日志:
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffcea601bd0) → Saving <NSManagedObjectContext (0x7ffcea601bd0): *** UNNAMED ***> on *** BACKGROUND THREAD ***
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffcea601bd0) → Save Parents? 1
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffcea601bd0) → Save Synchronously? 1
[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x7ffcea601bd0) Context UNNAMED is about to save. Obtaining permanent IDs for new 22 inserted objects
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffceba008f0) → Saving <NSManagedObjectContext (0x7ffceba008f0): *** DEFAULT ***> on *** BACKGROUND THREAD ***
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffceba008f0) → Save Parents? 1
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffceba008f0) → Save Synchronously? 1
[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x7ffceba008f0) Context DEFAULT is about to save. Obtaining permanent IDs for new 22 inserted objects
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffcea746c10) → Saving <NSManagedObjectContext (0x7ffcea746c10): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD ***
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffcea746c10) → Save Parents? 1
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffcea746c10) → Save Synchronously? 1
[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x7ffcea746c10) Context BACKGROUND SAVING (ROOT) is about to save. Obtaining permanent IDs for new 22 inserted objects
_70-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:]_block_invoke21(0x7ffcea746c10) → Finished saving: <NSManagedObjectContext (0x7ffcea746c10): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD ***
原来是我的谓词有问题。
NSArray *following 在 FRC 的 getter 中被硬设置,但在 getPosts api 调用完成之前它是空的。
我的表视图不会被 nsfetchedresultscontroller 中拉取的数据填充,直到应用程序重新启动或我转到另一个视图控制器并返回。我以前从来没有遇到过这个问题,很奇怪。
代码:
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 60, 0);
[super viewDidLoad];
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
// Update to handle the error appropriately.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
exit(-1); // Fail
}
UIRefreshControl *refresh = [[UIRefreshControl alloc] init];
[refresh addTarget:self
action:@selector(refresh)
forControlEvents:UIControlEventValueChanged];
self.refreshControl = refresh;
UITableViewController *tableVC = [[UITableViewController alloc]initWithStyle:UITableViewStylePlain];
[tableVC setTableView:self.tableView];
tableVC.refreshControl = self.refreshControl;
[self.tableView setContentOffset:CGPointMake(0.0f, -60.0f)
animated:YES];
[self getPosts];
// Do any additional setup after loading the view.
}
getPosts 获取 tableview 的所有帖子并将它们保存到 coredata。
-(void)getPosts
{
[self.refreshControl beginRefreshing];
[self.postsController getPostsFeedWithCompletion:^(BOOL complete, NSArray *posts) {
[self.refreshControl endRefreshing];
} failure:^(NSString *message) {
[self.refreshControl endRefreshing];
ALAlertBanner *alert = [ALAlertBanner alertBannerForView:self.view
style:ALAlertBannerStyleFailure
position:ALAlertBannerPositionTop
title:@"Error"
subtitle:@"Error retrieving posts, please try again."];
[alert show];
}];
}
getPostsFeedWithCompletion 方法:
-(void)getPostsFeedWithCompletion:(void (^)(BOOL complete, NSArray *posts))complete
failure:(void (^)(NSString *message))failure
{
[[APIManager sharedManager] getPath:@"posts/feed"
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
DLog(@"response: %@", responseObject);
NSArray __block *posts;
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext){
posts = [self createPosts:responseObject[@"posts"] inContext:localContext];
} completion:^(BOOL success, NSError *error) {
if(complete){
complete(YES, posts);
}
}];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
DLog(@"error: %@", error);
if(failure){
failure(@"Error retrieving posts");
}
}];
}
这里是 nsfetchedresultscontroller 实例化
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSManagedObjectContext *context = [NSManagedObjectContext MR_contextForCurrentThread];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"Post" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *following = [[SessionManager getInstance].currentLoggedInUser.follows allObjects];
NSMutableArray *predicateArray = [NSMutableArray array];
NSDate *now = [NSDate date];
[predicateArray addObject:[NSPredicate predicateWithFormat:@"account IN %@", following]];
[predicateArray addObject:[NSPredicate predicateWithFormat:@"expiration > %@", now]];
NSCompoundPredicate *filterPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicateArray];
[fetchRequest setPredicate:filterPredicate];
[fetchRequest setFetchBatchSize:20];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:@"expiration" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:context
sectionNameKeyPath:nil
cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
这是来自 MagicalRecord 保存的日志:
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffcea601bd0) → Saving <NSManagedObjectContext (0x7ffcea601bd0): *** UNNAMED ***> on *** BACKGROUND THREAD ***
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffcea601bd0) → Save Parents? 1
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffcea601bd0) → Save Synchronously? 1
[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x7ffcea601bd0) Context UNNAMED is about to save. Obtaining permanent IDs for new 22 inserted objects
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffceba008f0) → Saving <NSManagedObjectContext (0x7ffceba008f0): *** DEFAULT ***> on *** BACKGROUND THREAD ***
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffceba008f0) → Save Parents? 1
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffceba008f0) → Save Synchronously? 1
[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x7ffceba008f0) Context DEFAULT is about to save. Obtaining permanent IDs for new 22 inserted objects
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffcea746c10) → Saving <NSManagedObjectContext (0x7ffcea746c10): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD ***
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffcea746c10) → Save Parents? 1
[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x7ffcea746c10) → Save Synchronously? 1
[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x7ffcea746c10) Context BACKGROUND SAVING (ROOT) is about to save. Obtaining permanent IDs for new 22 inserted objects
_70-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:]_block_invoke21(0x7ffcea746c10) → Finished saving: <NSManagedObjectContext (0x7ffcea746c10): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD ***
原来是我的谓词有问题。
NSArray *following 在 FRC 的 getter 中被硬设置,但在 getPosts api 调用完成之前它是空的。