NSFetchedResultsController 在更新后看不到新的插入/删除获取的值

2024-01-08

在阅读了数十个类似的问题后,我想以这样的说法开始:“我确实设置了 NSFetchedResultsController 的委托,但它不起作用。”。

所以我有一个简单的 TableViewController,其单元格填充有 NSFetchedResultsController。这是 FRC 初始化代码:

@property (strong, nonatomic) NSFetchedResultsController *frc;

...

- (NSFetchedResultsController *)frc
{
    if (!_frc)
    {
        NSError *error = nil;
        NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:e_product];
        request.sortDescriptors = [NSArray arrayWithObjects:
                               [NSSortDescriptor sortDescriptorWithKey:@"product_group.product_group_name" ascending:YES],
                               [NSSortDescriptor sortDescriptorWithKey:f_product_name ascending:YES],
                               nil];
        _frc = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:[DTGGlobalSettings sharedInstance].moc sectionNameKeyPath:@"product_group.product_group_name" cacheName:nil];
        _frc.delegate = self;
        [_frc performFetch:&error];
        if (error)
        {
            NSLog(@"Error while fetching products: %@!", error.userInfo);
        }
    }

    return _frc;
}

我还使用一些调试标签实现了 NSFetchedResultsController 委托方法:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    // The fetch controller is about to start sending change notifications, so prepare the table view for updates.
    NSLog(@"controllerWillChangeContent");
    [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:
        NSLog(@"didChangeObject - insert");
        [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeDelete:
        NSLog(@"didChangeObject - delete");
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeUpdate:
        NSLog(@"didChangeObject - update");
        [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
        break;

    case NSFetchedResultsChangeMove:
        NSLog(@"didChangeObject - move");
        [tableView deleteRowsAtIndexPaths:[NSArray
                                           arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        [tableView insertRowsAtIndexPaths:[NSArray
                                           arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;
}
}


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id )sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {

switch(type) {

    case NSFetchedResultsChangeInsert:
        NSLog(@"didChangeSection - insert");
        [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeDelete:
        NSLog(@"didChangeSection - delete");
        [self.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.
NSLog(@"controllerDidChangeContent");
[self.tableView endUpdates];
}

在我的导航栏中,我有刷新按钮,其功能是启动产品目录方法,该方法执行以下操作: 1.从远程MySQL服务器获取产品 2. 如果具有 ID 的产品不存在 - 创建它并填写所有字段 3. 如果存在,则根据获取的值更新所有字段

在第 2 行和第 3 行之后,商店被保存。 我对应用程序中的所有 CoreData 操作使用单个 NSManagedObjectContext。

当我第一次启动应用程序时,TVC 是空的,因为尚未获取任何产品。当我按“刷新”时,将获取新产品并将其插入到 ManagedObjectContext 中,但 NSManagedObjectContext 没有看到/听到任何更改:没有调用委托方法,因此没有新行添加到 TVC。 当我重新启动应用程序时,新产品会毫无问题地提取到 TVC 中。

如果我在有一些产品时再次按刷新按钮,则在短暂延迟后它们都会消失。一些调试向我表明,如果在更新实体的字段(实际上值相同)并保存商店后发生。这次的委托方法就像一个魅力,对于每个更新和保存的实体控制器:didChangeObject:atIndexPath:forChangeType:newIndexPath 都通过 forChangeType = NSFetchedResultsChangeDelete 调用。

问题#1:为什么 NSFetchedResultsController 在不重新启动应用程序的情况下看不到插入的实体? 问题#2:为什么 NSFetchedResultsController 将已获取的实体标记为“不存在”(?)并在存储保存后将它们从 TVC 中删除?

我将不胜感激任何帮助和想法,上周整个星期都在与这个问题作斗争;(

UPD1(对于乔迪):以下是一些细节。我使用自定义类 DTGGlobalSettings 在应用程序中共享一些变量。这就是我初始化其sharedInstance属性的方式:

+(DTGGlobalSettings *)sharedInstance
{
    static DTGGlobalSettings *myInstance = nil;

    if (nil == myInstance)
    {
        myInstance = [[[self class] alloc] init];
        // set values here
        // try to acces MOC to init CoreData 
        [myInstance moc];        
        myInstance.baseURL = @"http://local.app/";
}
return myInstance;
}

为了初始化 CoreData 堆栈,我使用了 Apple 文档中的示例,因为出于某种原因,我在创建新项目时没有看到“使用 CoreData”复选框。我确信我以前在 Xcode 中见过它,但现在我没有;( (Xcode 4.4.1):

#pragma mark Core Data stack

- (NSManagedObjectContext *) moc {

if (_moc != nil) {
    return _moc;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
    _moc = [[NSManagedObjectContext alloc] init];
    [_moc setPersistentStoreCoordinator: coordinator];
}
return _moc;
}


- (NSManagedObjectModel *)managedObjectModel {

if (_managedObjectModel != nil) {
    return _managedObjectModel;
}
_managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];    
return _managedObjectModel;
}


- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

if (_persistentStoreCoordinator != nil) {
    return _persistentStoreCoordinator;
}
NSURL *storeUrl = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
storeUrl = [storeUrl URLByAppendingPathComponent:DOC_NAME];

NSError *error;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];

if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {
    NSLog(@"Error adding a store to the coordinator: %@, %@", error, error.userInfo);
}        
return _persistentStoreCoordinator;
}

-(void)saveDataStore
{
    NSError *error;
    if (![self.moc save:&error]) NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}

然后,DTGGlobalSettings 的“moc”(ManagedObjectContext)属性将在应用程序中需要访问 CoreData 的任何地方使用。

现在进入第二部分,更新数据库。我从远程 Web 服务器获取一些 JSON 格式的新实体,遍历生成的字典并为请求结果中找到的每个实体调用 createFromDictionary 方法。这是代码:

+(Product *)createFromDictionary:(NSDictionary *)entityData inContext:(NSManagedObjectContext *)moc performUpdate:(BOOL)update
{
Product *result;
if (update)
{
    NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:e_product];
    request.predicate = [NSPredicate predicateWithFormat:@"%K = %@", f_product_id, [entityData objectForKey:f_product_id]];
    result = [[DTGGlobalSettings sharedInstance].moc executeFetchRequest:request error:nil].lastObject;
    if (!result)
    {
        NSLog(@"Error updating Product ID %@! Cannot fetch entity.", [entityData objectForKey:f_product_id]);
        return nil;
    }
} else
{
    result = [NSEntityDescription insertNewObjectForEntityForName:e_product inManagedObjectContext:[DTGGlobalSettings sharedInstance].moc];
}

result.product_id = [[DTGGlobalSettings sharedInstance].numFormatter numberFromString:[entityData objectForKey:f_product_id]];
result.product_image = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[DTGGlobalSettings sharedInstance].baseURL stringByAppendingString:[entityData objectForKey:f_product_image]]]];
result.product_name = [entityData objectForKey:f_product_name];

return result;
}

当我用完所连接的实体时,我调用 [[DTGGlobalSettings sharedInstance] saveDataStore] (见上文)。此时,TVC 中的现有行(如果有)消失。如果我添加一些新实体,在保存时什么也不会发生,即 TVC 不会更新其行。


事实上,我认为你的第一个预编辑帖子已经包含了所有必要的信息。我只是没有读它(我不喜欢一直向右滚动阅读长行代码,有时只是不这样做 - 我的错)。

您的问题似乎与您的 FRC 排序描述符有关。

FRC 不能很好地保持关系排序描述符的更新。

有些人认为它就是这样设计的。我认为这是一个错误。

看这个帖子更改托管对象属性不会触发 NSFetchedResultsController 更新表视图 https://stackoverflow.com/questions/12370521/changing-a-managedobject-property-doesnt-trigger-nsfetchedresultscontroller-to/12379824#12379824就我而言。希望您会发现与您的案例的相似之处。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

NSFetchedResultsController 在更新后看不到新的插入/删除获取的值 的相关文章

  • 从iOS iphone中相机返回的图像中读取GPS数据

    我需要获取使用 iOS 设备相机拍摄的图像的 GPS 坐标 我不关心相机胶卷图像 只关心使用 UIImagePickerController SourceType Camera 拍摄的图像 我读过很多 stackoverflow 答案 比如
  • 无法更改 UITabBarItem.image:CSI 中不支持的像素格式

    我试图通过代码更改选项卡栏中显示的图像 我目前正在使用 Swift 和 Xcode 6 beta 3 我导入了 tabBarImage png 并 电子邮件受保护 cdn cgi l email protection在 Images xca
  • 管理 iOS 中的布局

    我是新来的iOS开发方面 我对 JAVA Swing 和 Windows 应用程序有扎实的背景 我想学习如何进行布局iOS 我猜iOS没有 布局管理器 就像 Java Swing 中的那样 发展的唯一出路UI是否指定每个控制器的尺寸和位置
  • 在 wkwebview 中启用摄像头和麦克风访问

    我有一个针对移动设备优化的网络应用程序 它利用getUserMedia访问网络摄像头和麦克风资源 我正在将这个应用程序包装在WKWebView因为我想提供原生应用程序体验 我知道 iOS 不允许通过浏览器访问相机 但是有什么方法可以使用本机
  • 有没有办法反转 SKSpriteNode 的颜色

    我想知道是否可以反转 SKSpriteNode 的颜色 或调整色调 您可以通过应用带有 SKEffect 节点的 CIFilter 来反转颜色 像这样的东西应该有效 SKEffectNode effectNode SKEffectNode
  • 使用 Xcode 6 XLIFF 导出的 iOS 本地化/国际化设置 Bungle

    背景 Xcode 6 添加了快速导出功能 可为每种语言创建单个 XLIFF 文件 只需从文件导航器中选择您的项目 然后选择菜单项编辑器 导出以进行本地化 Issue 它工作得非常好 并且 XML 中包含了所有内容 除了设置捆绑字符串 有人有
  • 查找 NSString 中子字符串的所有位置(不仅仅是第一个)

    有一个子串在字符串中出现多次 我用rangeOfString 不过好像只能找到第一个位置 如何找到子字符串的所有位置 NSString subString1 NSString subString2 n NSRange range1 newr
  • UIPopViewController 不工作

    我有一个 xib 文件 其中有 h 和 m 链接 在 xib 中有一个带有 textView 的 UIView 我想要对该视图执行的操作是 当您单击按钮时将其作为 UIPopViewController 打开 这是我的代码 IBAction
  • iOS Swift 3 以编程方式将文件复制到 iCloud Drive

    在我的我有文档下载选项 当用户从我的应用程序下载文档时 我需要将其存储到已安装在用户手机中的用户 iCloud Drive 我已在 Web 和 Xcode 中配置了 iCloud 但问题是我无法将文件正确复制到 iCloud Drive 文
  • 如何在 UIImagePickerController 捕获图像的瞬间获取当前位置?

    我研究了如何从返回的图像中获取位置数据UIImagePickerController相机 但是 我认为最简单的方法是获取当前位置CLLocationManager此刻UIImagePickerController捕获图像 有办法做到这一点吗
  • ios UICollectionView - 设置自动高度

    我正在使用 UICollection 视图创建 3x4 按钮矩阵 iPhone4很好看 高度也比较小 此外 集合视图不会滚动 因为它在可用空间中显示 3x4 矩阵按钮 现在 当我在 iPhone5 上运行相同的应用程序时 我看到底部按钮矩阵
  • 是否可以在不点击的情况下显示多个标记的多个信息窗口?

    我想在谷歌地图中显示多个标记的多个信息窗口 信息窗口应该在不点击标记本身的情况下显示 是否可以 经过研究 我了解到将标记设置为地图视图选定标记可以使信息窗口显示而无需点击它 但是 不能一次选择多个标记作为地图视图的选定标记 有什么可以做的吗
  • 具有 3D 旋转功能的 CAEmitterCell

    我正在尝试使用 CAEmitterLayer 和 CAEmitterCell 重现从顶部落下的小纸片效果 到目前为止 我得到了它的 2D 动画 但是我很难让每个单元格在掉落时旋转 如何对每个粒子应用随机旋转 我尝试过 3D Transfor
  • 使用 Xcode 资产目录缓存 UIImage

    我们都知道UIImage神秘的幕后缓存机制imageNamed 方法 在苹果的UIImage 类参考 https developer apple com library IOS documentation UIKit Reference U
  • NSXMLParser 解析使用 Windows-1256 编码的 xml 文件

    我想解析 Windows 1256 编码的 rss 文件 但解析器没有读取它 我用 UTF8 编码做了很多解析 但只有这个不起作用 为什么 带有 Windows 1256 的 rss 文件 http youm7 com Rss asp 解决
  • 在 Xcode 中查看 TestFlight 崩溃日志

    我已将我的应用程序发送给 TestFlight 的一些外部测试人员 仅当您从 testFlight 安装应用程序时才会出现问题 如果我从 Xcode 安装它 一切都很好 因此 我必须从 iPhone 中删除我的应用程序 并将自己添加为外部测
  • iOS 框架问题:类在两者中均实现

    我正在开发一个使用第三方框架类的iOS框架项目 所以我在下面添加了第三方框架链接的框架和库部分 当我在 iOS 应用程序项目中添加自定义框架时 每个类都会收到此警告 objc 3139 类 class name 在两者中均实现 privat
  • 在 UIScrollView Swift 中禁用垂直滚动

    不要将此问题标记为重复 我读了很多问题 但没有找到问题的答案 我的问题如下 我有一个UIScrollView它应该只水平滚动 这里它垂直滚动 20px 奇怪的事实 它似乎与状态栏的高度相同 我尝试打印内容大小 y 偏移量和高度UIScrol
  • iOS Javascript 引擎 parseFloat(1) 返回负数

    这段代码将使错误出现 function causeBug d var k var n parseFloat 1 var c Math abs d if n lt 0 k else k return k n function for var
  • 如何从我的 appDelegate 访问我的 viewController? iOS系统

    我有一个在 xCode 中创建为 基于视图的应用程序 的 iOS 应用程序 我只有一个 viewController 但它会自动显示 而且我没有看到任何将它与我的 appDelegate 关联的代码 我需要将数据从 appDelegate

随机推荐

  • Cordova 视频编辑器插件 InvalidOutputFormatException

    我在用着科尔多瓦插件视频编辑器 https www npmjs com package cordova plugin video editor处理以前录制的视频 该插件开始转换 但由于某种原因失败 我得到的错误是这样的 net yprest
  • 该程序集是由比当前加载的运行时更新的运行时构建的,无法加载

    我收到此错误 无法加载文件或程序集 Twitterizer2 Asynchronous 或其中之一 它的依赖项 该程序集是由比 当前已加载运行时且无法加载 但我已经从我的引用中删除了 twitterizer2 Asynchronous 库
  • 如何管理服务器上的数据库连接?

    我的 Web 应用程序中的数据库连接存在严重问题 由于我对单例数据库类的整个应用程序使用单个数据库连接 因此如果我尝试并发数据库操作 两个用户 数据库将回滚事务 这是我使用的静态方法 所有线程 servlet 都调用静态 Database
  • 当单元格更改时,VBA 运行宏,但如果通过宏则不运行

    好吧 我不确定这是否容易实现 但我会尝试 如果单元格发生更改 我使用此子程序来执行一些宏 Private Sub Worksheet Calculate Dim target As Range Set target Range b4 If
  • 将蛇形字符串转换为标题大小写

    我有以下蛇形变量big animal我想将其转换为Big Animal 我的方法是str gt str replace w g g gt g 1 toUpperCase 但我不断得到bigAnimal 但我想保留空格并将第一个字母大写 另一
  • C - 未定义的引用 - 是否有使用 -lm 编译的替代方法?

    我有一个很像这个问题的问题here https stackoverflow com questions 5248919 c undefined reference to sqrt其中错误是 未定义对 sqrt 的引用 我了解如何在编译时使用
  • Python 连接列表中的数组

    我有一个相同大小的数组列表 列表 z 包含 gt gt gt z 0 Out 24 array 27 56272878 952 8099842 3378 58996244 4303 9692863 gt gt gt z 1 Out 25 a
  • 如何在 Google Chrome 中暂时禁用 websocket?

    我想暂时禁用 Google Chrome 中的 websocket 来调试 javascript 以确保它适用于任何不支持 websocket 的浏览器 首先 我想说有更好的机制可以在无 websocket 环境中测试 JavaScript
  • 限制对 ASP.Net MVC 站点的匿名访问的问题

    每当我限制 MVC 站点中的匿名访问时 我都会收到 404 错误 应用程序中的服务器错误 无法找到该资源 描述 HTTP 404 您正在查找的资源 或其依赖项之一 可能已被删除 名称已更改或暂时不可用 请检查以下 URL 并确保其拼写正确
  • 跨不同程序开发的库的 Subversion 存储库布局

    我负责几个 相当小的 程序 它们通过不同的库共享大量代码 我想知道开发不同程序 和库 的最佳存储库布局是什么 并使库在所有程序之间保持同步 为了便于讨论 我们假设有两个带有两个库的程序 Program1 Library1 Library2
  • 检查文件是否存在的最快方法[重复]

    这个问题在这里已经有答案了 我使用的方法只是尝试 fopen 要检查的文件 does file exist char fname 999 whatever constructed during execution FILE fp NULL
  • sql.Identifier 不带引号

    我在网上搜索 sql Identifier without quoting 并且这个帖子 https stackoverflow com questions 43877210 how to remove the quotes from a
  • R 闪亮登录黑客

    在尝试了 RStudio Shiny Pro Server 的评估后 我对登录 身份验证机制不太感兴趣 因为它们不是管理客户端访问闪亮应用程序的用户帐户的简单机制 因此 我试图在 Shiny 中创建自己的登录机制 除了在shinydashb
  • .NET 客户端编程中出现异常“AMQP 操作被中断”(代码=406)

    我有一个 2 8 2 RabbitMQ 服务器和一个 2 8 2 客户端 dll 有声明队列并获取消息的代码 它工作正常 所有参数都正确 IModel channel null ConnectionFactory factory new C
  • Windows 工作流程 4.0 InstancePersistenceCommand 错误

    我有一个 wcf 工作流程 其中有三个按顺序排列的接收活动 IE 1 接收申请 2 经理1批准 3 最终经理批准 我的问题是 我能够使用客户端应用程序中的工作流程并调用第一个 接收应用程序活动 但是当我尝试调用第二个 manager1 批准
  • Android 中的轮播动画

    请参阅下面的屏幕 我尝试使用封面流来实现此动画 就像我们作为轮播动画一样 但我没有得到与屏幕中所示相同的效果 如果有人做过这种类型的动画 请将代码片段发送给我 我前段时间在我的应用程序中遇到了类似的问题 虽然我没有处理过您在图像右下角显示的
  • 在 R 中的同一张图上绘制多列[重复]

    这个问题在这里已经有答案了 我有以下数据框 A B C D Xax 0 451 0 333 0 034 0 173 0 22 0 491 0 270 0 033 0 207 0 34 0 389 0 249 0 084 0 271 0 54
  • RxJava2 + Room:clearAllTables() 调用后数据未插入数据库

    成功后在我的Android应用程序中login我将会话信息保存在 Room 中 然后从 BE 检索用户信息并保存它 一切正常 我可以看到数据库表中保存的信息 When 用户注销从应用程序中 所有表都通过 appDatabase clearA
  • 如何制作撤消/重做功能

    我想添加一个undo redo我的脚本中的函数 我环顾四周 看到了一些建议 其中大多数建议使用command pattern 该函数必须在一页上运行 重新加载页面后 该函数必须能够redo undo最后的事情 我不知道命令模式是如何工作的
  • NSFetchedResultsController 在更新后看不到新的插入/删除获取的值

    在阅读了数十个类似的问题后 我想以这样的说法开始 我确实设置了 NSFetchedResultsController 的委托 但它不起作用 所以我有一个简单的 TableViewController 其单元格填充有 NSFetchedRes