- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我有一个带有谓词的fetchedResultsController,其中"isOpen == YES"
当调用 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。但这没有用。或者使用它们是有意义的......
编辑:从头开始,它确实有效,在我的 resultsController 上执行 performFetch 后立即调用 reloadData,但使用 reloadData 正在敲定一个解决方案。另外,它会删除所有动画。我希望我的 Controller 自动更新我的 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];
}
第一次更新:
Tracking [managedObjectContext hasChanges] 确实返回 YES,这是应该的。但是 fetchedResultsController 没有更新 tableView
第二次更新
didChangeObject:atIndexPath: 没有被调用 对于这种特殊情况!我还有 2 个方法,使用完全相同的代码,它们只是碰巧是不同的实体。他们工作得很好。感谢@Leonardo 指出这一点
第三次更新 这个方法遵循同样的规则。但确实有效。
- (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];
}
有人对我可能遗漏的内容有任何其他想法吗?
谢谢,
努诺
最佳答案
OK,我会解释你的问题,然后让你判断是不是FRC的bug。如果您认为这是一个错误,那么您真的应该向 Apple 提交错误报告。
你的获取结果 Controller 谓词是这样的:
NSString *predicate = [NSString stringWithFormat: @"clockSet.isOpen == YES"];
这是 bool 值的有效谓词。它将遵循 clockSet
实体的关系并获取其 isOpen
属性。如果是 YES
,那么这些对象将被接受到对象数组中。
我认为我们到此为止都很好。
现在,如果您将 clockSet.isOpen
属性之一更改为 NO
,那么您希望看到该对象从您的 TableView 中消失(即,它不应再匹配谓词,因此它应该从获取的对象数组中删除)。
所以,如果你有这个......
[currentClockSet setIsOpen:[NSNumber numberWithBool:NO]];
然后,无论哪个顶级对象与 currentClockSet
有关系,都应该从您的 FRC 获取结果数组中“消失”。
但是,您并没有看到它消失。原因是FRC监控的对象没有变化。是的,谓词键路径发生了变化,但 FRC 包含实体 ClockPair
和 ClockSet
实体实际上发生了变化。
您可以观看通知飞来飞去,看看幕后发生了什么。
无论如何,FRC 将在您进行抓取时使用关键路径,但它不会监视对不在其实际抓取对象集中的对象的更改。
最简单的解决方法是为包含此关键路径对象的对象“设置”一个属性。
例如,我注意到 ClockPair
也有一个 isOpen
属性。如果你有逆向关系,那么你可以这样做......
currentClockSet.isOpen = NO;
currentClockSet.clockPair.isOpen = currentClockSet.clockPair.isOpen;
请注意,您实际上根本没有更改该值。然而,setter 被调用,这触发了 KVO,因此私有(private)的 DidChange 通知,然后告诉 FRC 对象改变了。因此,它会重新评估检查以查看是否应包含该对象,发现 keypath 值已更改,然后执行您期望的操作。
因此,如果您在 FRC 谓词中使用关键路径,如果您更改该值,则需要蠕动回到 FRC 数组中的所有对象并“弄脏它们”,以便这些对象位于传递有关对象更改的通知。这很丑陋,但可能比保存或更改您的提取请求并重新提取要好。
我知道你不相信我,所以继续尝试吧。请注意,要使其正常工作,您必须知道 FRC 对象数组中的哪些项目会受到更改的影响,并“戳”它们以使 FRC 注意到更改。
如前所述,另一种选择是保存上下文并重新获取值。如果您不想保存上下文,则可以使获取包含当前上下文中的更新,而无需从存储中刷新。
我发现,对 FRC 正在监视的对象进行伪造更改是完成对作为其他实体的关键路径的谓词进行重新评估的最佳方式。
好的,所以,这是否是错误还有待商榷。就我个人而言,我认为如果 FRC 要监控 key 路径,它应该一直监控,而不是像我们在这里看到的那样部分监控。
我希望这是有道理的,我鼓励您提交错误报告。
关于objective-c - 更改托管对象属性不会触发 NSFetchedResultsController 更新 TableView ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12370521/
你能比较一下属性吗 我想禁用文本框“txtName”。有两种方式 使用javascript,txtName.disabled = true 使用 ASP.NET, 哪种方法更好,为什么? 最佳答案 我
Count 属性 返回一个集合或 Dictionary 对象包含的项目数。只读。 object.Count object 可以是“应用于”列表中列出的任何集合或对
CompareMode 属性 设置并返回在 Dictionary 对象中比较字符串关键字的比较模式。 object.CompareMode[ = compare] 参数
Column 属性 只读属性,返回 TextStream 文件中当前字符位置的列号。 object.Column object 通常是 TextStream 对象的名称。
AvailableSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。 object.AvailableSpace object 应为 Drive 
Attributes 属性 设置或返回文件或文件夹的属性。可读写或只读(与属性有关)。 object.Attributes [= newattributes] 参数 object
AtEndOfStream 属性 如果文件指针位于 TextStream 文件末,则返回 True;否则如果不为只读则返回 False。 object.A
AtEndOfLine 属性 TextStream 文件中,如果文件指针指向行末标记,就返回 True;否则如果不是只读则返回 False。 object.AtEn
RootFolder 属性 返回一个 Folder 对象,表示指定驱动器的根文件夹。只读。 object.RootFolder object 应为 Dr
Path 属性 返回指定文件、文件夹或驱动器的路径。 object.Path object 应为 File、Folder 或 Drive 对象的名称。 说明 对于驱动器,路径不包含根目录。
ParentFolder 属性 返回指定文件或文件夹的父文件夹。只读。 object.ParentFolder object 应为 File 或 Folder 对象的名称。 说明 以下代码
Name 属性 设置或返回指定的文件或文件夹的名称。可读写。 object.Name [= newname] 参数 object 必选项。应为 File 或&
Line 属性 只读属性,返回 TextStream 文件中的当前行号。 object.Line object 通常是 TextStream 对象的名称。 说明 文件刚
Key 属性 在 Dictionary 对象中设置 key。 object.Key(key) = newkey 参数 object 必选项。通常是 Dictionary 
Item 属性 设置或返回 Dictionary 对象中指定的 key 对应的 item,或返回集合中基于指定的 key 的&
IsRootFolder 属性 如果指定的文件夹是根文件夹,返回 True;否则返回 False。 object.IsRootFolder object 应为&n
IsReady 属性 如果指定的驱动器就绪,返回 True;否则返回 False。 object.IsReady object 应为 Drive&nbs
FreeSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。只读。 object.FreeSpace object 应为 Drive 对象的名称。
FileSystem 属性 返回指定的驱动器使用的文件系统的类型。 object.FileSystem object 应为 Drive 对象的名称。 说明 可
Files 属性 返回由指定文件夹中所有 File 对象(包括隐藏文件和系统文件)组成的 Files 集合。 object.Files object&n
我是一名优秀的程序员,十分优秀!