gpt4 book ai didi

ios - NSFetchedResultsController indexPathForObject 不计算部分

转载 作者:行者123 更新时间:2023-11-29 02:25:46 25 4
gpt4 key购买 nike

我正在更新单元格上的下载 View /按钮,当我去更新我的单元格时,我没有得到正确的部分。

我获取索引和更新下载进度的代码是这样的:

Object *obj = (Object *)notification.object;
NSIndexPath *index = [self.fetchedResultsController indexPathForObject:obj];
MyTableViewCell *cell = (MyTableViewCell *)[self.tableView cellForRowAtIndexPath:index];
DownloadProgressButtonView *buttonView = (DownloadProgressButtonView *)cell.accessoryView;
NSNumber *progressLong = [notification.userInfo objectForKey:@"progress"];
float progress = [progressLong floatValue];
NSNumber *totalBytesLong = [notification.userInfo objectForKey:@"totalBytes"];
float totalBytes = [totalBytesLong floatValue];
buttonView.progress = progress *.01;
float totalDownloadEstimate = totalBytes / 1.0e6;
float megaBytesDownloaded = (progress *.01) * totalDownloadEstimate;
cell.bottomLabel.text = [NSString stringWithFormat:@"%.1f MB of %.1f MB", megaBytesDownloaded, totalDownloadEstimate];

如果我有两个对象,每个对象在不同的​​部分,它们有相同的行 (0)。当我去更新我的单元格时,它会更新第 1 节而不是第 0 节中的单元格。我该如何解决这个问题?

我可以放置任何其他需要的代码。如果我只是禁用我的 NSFetchedResultsController 中的部分,它会完美地工作。

我的 NSFetchedResultsController 和委托(delegate)。

- (NSFetchedResultsController *)fetchedResultsController
{

if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Object" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];

NSSortDescriptor *nameString = [[NSSortDescriptor alloc] initWithKey:self.sectionSortDescriptor ascending:NO];
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:self.sortDescriptor ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:nameString,descriptor, nil]];
NSString *downloadStartedString = @"Preparing to download";
NSString *downloadingString = @"Downloading";
NSString *downloadPausedString = @"Download paused";
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"(downloaded == YES) OR (downloadStatus like[cd] %@) OR (downloadStatus like[cd] %@) OR (downloadStatus like[cd]%@)",downloadPausedString, downloadStartedString,downloadingString];
[fetchRequest setFetchBatchSize:20];
_fetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext sectionNameKeyPath:self.sectionNameString
cacheName:nil];
_fetchedResultsController.delegate = self;
self.fetchedResultsController = _fetchedResultsController;

return _fetchedResultsController;
}

/*
NSFetchedResultsController delegate methods to respond to additions, removals and so on.
*/
- (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:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;

case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;

case NSFetchedResultsChangeUpdate:
[self configureCell:(StudioTableViewCell *)[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;

case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
}
}

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
switch(type)
{
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeMove:
NSLog(@"A table item was moved");
break;
case NSFetchedResultsChangeUpdate:
NSLog(@"A table item was updated");
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];
}

最后,当下载状态发生变化时,我更新对象并发送通知以使用新状态更新单元格:

- (void)updateCell:(NSNotification *)notification
{
Object *obj = (Object *)notification.object;
NSIndexPath *index = [self.fetchedResultsController indexPathForObject:obj];
[self.tableView reloadRowsAtIndexPaths:@[index] withRowAnimation:UITableViewRowAnimationFade];
}

最佳答案

以这种方式更新单元格是不可靠的。以这种方式更新的单元迟早会被重用。单元格的 subview 将根据数据源提供的数据由 tableView:cellForRowAtIndexPath: 重新配置。

您应该对 Object 本身进行更改(而不是将它们传递到通知的 userInfo 中)并保存托管对象上下文。然后 NSFetchedResultsControllerDelegate 回调将触发,允许您重新加载相应的行。然后你应该在 configureCell:atIndexPath 中设置 MyTableViewCell 的所有属性。

并且 configureCell: 方法应该从 cellForRowAtIndexPath 方法中调用,而不是从获取的结果 Controller 委托(delegate)方法中调用。一般模式是在 controllerDidChangeObject: 中调用 reloadRowsAtIndexPaths:。否则,您可能会遇到一些单元重用问题。

关于代码应该是什么样子的想法:

- (void)updateCell:(NSNotification *)notification
{
//depending on your Core Data contexts setup,
// you may need embed the code below in performBlock: on object's context,
// I omitted it for clarity
Object *obj = (Object *)notification.object;
//save changes to the object, for example:
NSNumber *progressLong = [notification.userInfo objectForKey:@"progress"];
obj.progress = progressLong;
//set all the properties you will need in configureCell:, then save context
[obj.magagedObjectContext save:&someError];
}

然后获取的结果 Controller 将调用controllerDidChangeObject:,在这个方法中你应该重新加载行:

    case NSFetchedResultsChangeUpdate:
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
break;

最后,配置单元格(假设您从 tableView:cellForRowAtIndexPath: 调用 configureCell:atIndexPath):

- (void)configureCell:(MyTableViewCell*)cell atIndexPath:(NSIndexPath*)indexPath {
Object *object = [self.fetchedResultsController objectAtIndexPath:indexPath];

DownloadProgressButtonView *buttonView = (DownloadProgressButtonView*) cell.accessoryView;
buttonView.progress = object.progress.floatValue *.01;
//and so on
}

关于ios - NSFetchedResultsController indexPathForObject 不计算部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27556691/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com