當我的用戶看到一張圖片時,她可以通過按下按鈕來欣賞它。下面的代碼運行:NSFetchedResultsController不更新?
- (void)feedback:(Item *)item isLiked:(bool)liked {
// Update the item with the new score asynchornously
NSManagedObjectID *itemId = item.objectID;
dispatch_async(dispatch_get_main_queue(), ^{
// Create a new managed object context and set its persistent store coordinator
// Note that this **must** be done here because this context belongs to another thread
AppDelegate *theDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *localContext = [[NSManagedObjectContext alloc] init];
[localContext setPersistentStoreCoordinator:[theDelegate persistentStoreCoordinator]];
Item *localItem = (Item *)[localContext objectWithID:itemId];
localItem.liked = [NSNumber numberWithBool:liked];
localItem.updated_at = [NSDate date];
NSError *error;
if (![localContext save:&error]) {
NSLog(@"Error saving: %@", [error localizedDescription]);
}
});
在我的應用程序中,LikedViewController顯示用戶喜歡的圖像。 LikedVC由一個連接到NSFetchedResultsController的UITableViewController組成。
LikedVC:
- (void)viewDidLoad
{
[super viewDidLoad];
// NSFetchedResultsController
NSManagedObjectContext *moc = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
_fetchedResultsController = \
[[NSFetchedResultsController alloc] initWithFetchRequest:[self.delegate getFetchRequest]
managedObjectContext:moc
sectionNameKeyPath:nil
cacheName:nil]; // TODO investigate whether we should bother with cache
_fetchedResultsController.delegate = self;
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
// Update to handle the error appropriately.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
exit(-1); // Fail
}
// Bottom loading bar
self.tableView.tableFooterView = self.footerView;
self.footerActivityIndicator.hidesWhenStopped = true;
// ActivityIndicator
self.activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
self.activityIndicator.color = [UIColor blackColor];
[self.tableView addSubview:self.activityIndicator];
self.activityIndicator.hidesWhenStopped = true;
// FIXME Unable to center it inside the tableView properly
self.activityIndicator.center = CGPointMake(self.tableView.center.x, self.tableView.center.y - self.tabBarController.tabBar.frame.size.height);
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// Automatically fetch when there is nothing in the UITableView
if ([self tableView:self.tableView numberOfRowsInSection:0] == 0) {
if ([self canFetch]) {
[self refill];
}
}
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
if (self.operation && self.operation.isExecuting) {
NSLog(@"Cancelling Operation: %@", self.operation);
[self.operation cancel];
self.isFetching = false;
}
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"FeedCell";
Item *item = [_fetchedResultsController objectAtIndexPath:indexPath];
FeedCell *cell = (FeedCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.item = item;
cell.tag = indexPath.row;
cell.customImageView.userInteractionEnabled = YES;
// NOTE Don't try to do this at the UITableViewCell level since the tap will be eaten by the UITableView/ScrollView
if (self.likeOnTap) {
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)];
tap.numberOfTapsRequired = 1;
[cell.customImageView addGestureRecognizer:tap];
}
// Set up the buttons
[cell.likeButton addTarget:self action:@selector(liked:) forControlEvents:UIControlEventTouchUpInside];
[cell.dislikeButton addTarget:self action:@selector(disliked:) forControlEvents:UIControlEventTouchUpInside];
[cell.detailButton addTarget:self action:@selector(detailed:) forControlEvents:UIControlEventTouchUpInside];
[[SDImageCache sharedImageCache] queryDiskCacheForKey:item.image_url done:^(UIImage *image, SDImageCacheType type) {
if (image) {
[cell setCustomImage:image];
} else {
// If we have to download, make sure user is on the image for more than 0.25s before we
// try to fetch. This prevents mass downloading when the user is scrolling really fast
double delayInSeconds = 0.25;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
if ([self isIndexPathVisible:indexPath]) {
[SDWebImageDownloader.sharedDownloader
downloadImageWithURL:[NSURL URLWithString:item.image_url]
options:0
progress:^(NSUInteger receivedSize, long long expectedSize) { }
completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) {
if (image && finished) {
[cell setCustomImage:image];
[[SDImageCache sharedImageCache] storeImage:image forKey:item.image_url];
}
}];
}
});
}
}];
// Check if we are almost at the end of the scroll. If so, start fetching.
// Doing this here is better than overriding scrollViewDidEndDragging
if (indexPath.row >= [self.tableView numberOfRowsInSection:0] - 3) {
[self refill];
}
return cell;
}
#pragma mark - Table view delegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id sectionInfo = [_fetchedResultsController.sections objectAtIndex:section];
NSInteger ret = [sectionInfo numberOfObjects];
self.hasContent = (ret != 0);
return ret;
}
# pragma mark - NSFetchedResultsControllerDelegate
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
NSLog(@"1");
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
NSLog(@"2");
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath {
NSLog(@"3");
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[NSException raise:@"Unknown update" format:@"NSFetchedResultsChangeUpdate: invoked"];
// [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[NSException raise:@"Unknown update" format:@"NSFetchedResultsChangeMove: invoked"];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
NSLog(@"4");
[self.tableView endUpdates];
}
(請注意,我省略了一些信息,以保持這個問題短期)
這是LikedVC
的fetchRequest- (NSFetchRequest *)getFetchRequest {
NSManagedObjectContext *moc = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Item" inManagedObjectContext:moc];
[request setPredicate:[NSPredicate predicateWithFormat:@"liked == %d OR origin == %d", 1, OriginsLike]];
[request setEntity:entity];
[request setResultType:NSManagedObjectResultType];
[request setFetchBatchSize:10];
NSSortDescriptor *d = [[NSSortDescriptor alloc] initWithKey:@"updated_at" ascending:NO selector:nil];
[request setSortDescriptors:[NSArray arrayWithObject:d]];
return request;
}
我看到有一個錯誤:用戶喜歡一個項目,但是當用戶切換到LikedVC時,該項目不會顯示在任何地方。我在tableView的controllerDidChangeContent,controllerWillChangeContent等方法中添加了NSLog(@「1」),NSLog(@「2」)......。我沒有看到「1」,「2」,..被記錄。
爲什麼我的NSFetchedResultsController不工作?
我讀了幾次,所以我不得不問:你期望在這裏發生什麼? 用戶點擊,並且' - (void)feedback:(Item *)item isLiked:(bool)liked'被觸發,並且您聲明它正常工作。 'LikedViewController'拿起剛剛喜歡的'Item'。你的照片來自哪裏?它是否在'Item'對象中被引用? 我不是一個NSFetchedController的巨大專家,但我不認爲它是按照您期望的方式觸發事件,並且似乎它的工作方式如果'喜歡'結果正確返回....? – 2013-04-11 00:23:37
@twairball更新了問題。基本上,反饋被解僱。我**認爲**反饋已正確執行。 NSFetchedResultsController沒有更新,因爲我沒有看到正在顯示的新項目 – disappearedng 2013-04-11 00:33:24