「isOpen == YES」という述語を持つfetchedResultsControllerがあります。
closeCurrentClockSetを呼び出すときは、そのプロパティをNOに設定します。したがって、tableView には表示されなくなります。
何らかの理由で、これは起こっていません。
誰かがこれを理解するのを手伝ってくれますか?
-(void)closeCurrentClockSet
{
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"isOpen == YES"];
NSArray *fetchedObjects =
[self fetchRequestForEntity:@"ClockSet"
withPredicate:predicate
inManagedObjectContext:[myAppDelegate managedObjectContext]];
ClockSet *currentClockSet = (ClockSet *)fetchedObjects.lastObject;
[currentClockSet setIsOpen:[NSNumber numberWithBool:NO]];
}
--
カスタムfetchRequestForEntity:withPredicate:inManagedObjectContextメソッドを呼び出すことにより、まったく同じアプローチを使用して、さらにいくつかのメソッドがあります。
これらのメソッドでは、プロパティを変更すると、tableView が正しく更新されます。しかし、これは上のもの ( closeCurrentClockSet ) ではありません! 理由がわかりません。
--
私の fetchedResultsController の実装は、Apple のドキュメントからのものです。
また、別の詳細。アプリをバックグラウンドに送信すると。それを閉じて再度開くと、tableView が更新されたように表示されます。
ここで、stackOverflow に関する以前の質問に従うために最善を尽くしました。運がない。私もこれを骨にNSLoggedしました。オブジェクトは正しく取得されています。それは正しいものです。isOpen プロパティは正しくNOに更新されています。しかし、何らかの理由で、私の fetchedResultsController は tableView を更新しません。
reloadData や performFetch の呼び出しなど、いくつかの「ハンマー」ソリューションを試しました。しかし、それはうまくいきませんでした。または、それらを使用する意味があります...
編集:それはうまくいきました.resultControllerでperformFetchの直後にreloadDataを呼び出しますが、reloadDataを使用すると解決策が打たれます。さらに、すべてのアニメーションを削除します。コントローラーで tableView を自動更新したい。
誰かがこれを理解するのを手伝ってくれますか?
どんな助けでも大歓迎です!
ありがとうございました、
ヌーノ
編集:
完全な実装。
fetchedResultsController はかなり標準的で簡単です。他のすべてはAppleのドキュメントからのものです
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController) {
return _fetchedResultsController;
}
NSManagedObjectContext * managedObjectContext = [myAppDelegate managedObjectContext];
NSEntityDescription *entity =
[NSEntityDescription entityForName:@"ClockPair"
inManagedObjectContext:managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:entity];
NSString *predicate = [NSString stringWithFormat: @"clockSet.isOpen == YES"];
[fetchRequest setPredicate: [NSPredicate predicateWithFormat:predicate]];
NSSortDescriptor *sortDescriptor1 =
[[NSSortDescriptor alloc] initWithKey:@"clockIn" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext
sectionNameKeyPath:nil
cacheName:@"Root"];
_fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
--
Apple のドキュメントの定型コード:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
// The fetch controller is about to start sending change notifications, so prepare the table view for updates.
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationTop];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationLeft];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationTop];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeSection:(id )sectionInfo
atIndex:(NSUInteger)sectionIndex
forChangeType:(NSFetchedResultsChangeType)type
{
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
[self.tableView endUpdates];
}
1回目の更新:
[managedObjectContext hasChanges]を追跡すると、当然のことながら YES が返されます。しかし、fetchedResultsController は tableView を更新しません
2回目の更新
didChangeObject:atIndexPath:は、この特定のケースでは呼び出されません! まったく同じコードを使用するメソッドがさらに 2 つありますが、それらはたまたま別のエンティティです。そして、それらは完璧に機能します。これを指摘してくれてありがとう@Leonardo
3回目の更新このメソッドは、同じルールに従います。しかし、実際には機能します。
- (void)clockOut
{
NSPredicate * predicate = [NSPredicate predicateWithFormat:@"isOpen == %@", [NSNumber numberWithBool:YES]];
NSArray * fetchedObjects =
[self fetchRequestForEntity:@"ClockPair"
withPredicate:predicate
inManagedObjectContext:[myAppDelegate managedObjectContext]];
ClockPair *aClockPair = (ClockPair *)fetchedObjects.lastObject;
aClockPair.clockOut = [NSDate date];
aClockPair.isOpen = [NSNumber numberWithBool:NO];
}
私が見逃している可能性があるものについて、他に何かアイデアはありますか?
ありがとうございました、
ヌーノ