使用NSFetchedResultsController循环时标题未更新问题求助
听起来你遇到的情况是:嵌套使用NSFetchedResultsController遍历数据时,strats.sexfluence_user_stratagy_title始终显示同一个值,但其他内容都能正常展示。我来帮你梳理几个最可能的原因和对应的解决办法:
一、检查NSFetchedResultsController的复用逻辑
你在循环里每次调用fetchedResultsControllerStrat:方法并赋值给self.fetchedResultsControllerStrats,如果这个属性的getter方法或者fetchedResultsControllerStrat:内部有缓存旧实例的逻辑(比如判断如果已经存在FRC就直接返回),那每次循环拿到的都是第一次创建的FRC,对应的fetchedObjects自然也是同一批数据,标题就会重复。
解决办法:确保fetchedResultsControllerStrat:每次调用都创建新的NSFetchedResultsController实例,并且不使用缓存。示例代码如下:
- (NSFetchedResultsController *)fetchedResultsControllerStrat:(NSNumber *)objectiveId { // 每次都创建新的请求和FRC,不复用旧实例 NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Stratagy"]; // 务必设置正确的排序器(FRC要求必须有排序) fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"sexfluence_user_stratagy_title" ascending:YES]]; // 用传入的objectiveId设置谓词,确保过滤对应的数据 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"sexfluence_user_objectives_id == %@", objectiveId]; fetchRequest.predicate = predicate; NSFetchedResultsController *frc = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil]; // 不要设置cacheName,避免缓存 // 执行获取数据操作 NSError *fetchError = nil; if (![frc performFetch:&fetchError]) { NSLog(@"获取Stratagy数据失败: %@", fetchError.localizedDescription); } return frc; }
二、验证谓词的正确性
如果fetchedResultsControllerStrat:里的谓词设置错误,比如用了固定值、变量名写错(比如把sexfluence_user_objectives_id写成了其他字段),就会导致每次都获取同一批Stratagy数据,标题自然不变。
你可以在循环里打印关键信息,排查数据是否匹配:
for (Objective * objs in self.fetchedResultsControllerObj.fetchedObjects) { NSLog(@"当前Objective ID: %@", objs.sexfluence_user_objectives_id); self.fetchedResultsControllerStrats = [self fetchedResultsControllerStrat:objs.sexfluence_user_objectives_id]; NSLog(@"对应Stratagy数量: %lu", (unsigned long)self.fetchedResultsControllerStrats.fetchedObjects.count); for (Stratagy * strats in self.fetchedResultsControllerStrats.fetchedObjects) { NSLog(@"Stratagy标题: %@", strats.sexfluence_user_stratagy_title); RADataObject *stratagies = [RADataObject dataObjectWithName:strats.sexfluence_user_stratagy_title... } }
如果发现不同Objective ID对应的Stratagy数量或标题完全一致,那肯定是谓词设置出了问题。
三、排查RADataObject的创建逻辑
另外,你用到的RADataObject dataObjectWithName:工厂方法如果内部有复用实例的逻辑(比如缓存了创建过的对象),也可能导致后续的标题被覆盖或者没有更新。
可以临时改成直接初始化RADataObject的方式测试:
RADataObject *stratagies = [[RADataObject alloc] init]; stratagies.name = strats.sexfluence_user_stratagy_title; // 其他属性赋值
如果这样标题正常了,那问题就出在这个工厂方法的缓存逻辑上,需要调整它的实现。
更优的替代方案:使用Core Data关系
其实如果Objective和Stratagy在Core Data模型里已经设置了一对多的关系(比如Objective有一个stratagies属性对应关联的所有Stratagy),完全可以不用嵌套FRC,直接通过关系获取数据,这样代码更简洁也更不容易出错:
for (Objective *objs in self.fetchedResultsControllerObj.fetchedObjects) { // 直接遍历Objective关联的Stratagy集合 for (Stratagy *strats in objs.stratagies) { RADataObject *stratagies = [RADataObject dataObjectWithName:strats.sexfluence_user_stratagy_title... // 后续逻辑 } }
内容的提问来源于stack exchange,提问作者Duny

