predicateWithFormat 返回错误的核心数据对象
Posted
技术标签:
【中文标题】predicateWithFormat 返回错误的核心数据对象【英文标题】:predicateWithFormat returns wrong Core data object 【发布时间】:2018-10-25 13:03:05 【问题描述】:我的应用程序包含从服务器接收并存储在核心数据中的图像对象。每个对象包含 image = NSData imageId = NSString 和 imageKeyword = NSString 为了检查是否有任何图像已从服务器中删除,应用程序接收一个 image_id 数组,该数组与应用程序中包含的 image_ids 进行比较,并从服务器中删除数组中未找到的任何图像。
该方法使用 NSPredicate 来查找应用程序从服务器接收的 allImageArray 中是否找到 imageId。未找到的对象被添加到 imageToDelete 数组中,然后从核心数据中删除。只要对象仅包含 imageId 和 image,此方法就可以正常工作。
-(void)updateLocalImagesFromActivitiesParents:(NSArray*)allImageArray
NSPredicate *imageIdsFilter = [NSPredicate predicateWithFormat:@"NOT (imageId IN %@)", allImageArray];
NSFetchRequest *imageIdsRequest = [ImageCD MR_requestAllWithPredicate:(NSPredicate *)imageIdsFilter];
NSArray *imagesToDelete = [ImageCD MR_executeFetchRequest:imageIdsRequest];
if([imagesToDelete count] > 0)
[MagicalRecord saveWithBlockAndWait:^(NSManagedObjectContext *localContext)
for(ActivityCD *imageToDelete in imagesToDelete)
[imageToDelete MR_deleteEntityInContext:localContext];
[localContext MR_saveToPersistentStoreAndWait];
];
但我注意到,每次我为 imageKeyword 分配一个值时,上述方法检测在 allImageArray 中找不到并删除它。我很难理解为什么会发生这种情况,因为 delete 方法应该只查找 imageid 但似乎也能检测到 imageKeyword 的变化。
已删除对象的日志中的示例。如前所述,ImageId =25245 在服务器的 allImageArray 中找到,并且仅在我将“word”添加到 imageKeyword 时才被删除。
"<ImageCD: 0x600003464c80> (entity: ImageCD; id: 0xa0c6b9257bed7492 <x-coredata://6454DD11-CEDB-40C2-B5E0-1FEE8006EE92/ImageCD/p26> ; data: \n image = <89504e47 0d0a1a0a 0000000d 49484452 00000280 00000203 08020000 001b8b38 02000020 00494441 54789c84 bd4982e5 b8ae>;\n imageId = 25245;\n imageKeyword = word;\n)"
这是我为对象分配 imageKeyWord 的方法。
-(void)setImageKeyWord
ImageCD *localImage = [ImageCD MR_findFirstByAttribute:@"imageId" withValue:[NSString stringWithFormat:@"%@", _choosenImageId]];
[MagicalRecord saveWithBlock:^(NSManagedObjectContext * _Nonnull localContext)
localImage.imageKeyword = _userCreate;
];
[self testingKeyWordSearch];
我猜我以某种方式分配了 imagKeyWord 错误,但我不知道怎么做。希望得到一些支持:)
【问题讨论】:
【参考方案1】:-(void)setImageKeyWord
[MagicalRecord saveWithBlock:^(NSManagedObjectContext * _Nonnull localContext)
ImageCD *localImage = [ImageCD MR_findFirstByAttribute:@"imageId"
withValue:[NSString stringWithFormat:@"%@", _choosenImageId]
inContext:localContext];
localImage.imageKeyword = _userCreate;
];
[self testingKeyWordSearch];
在您的代码中,您调用findFirstByAttribute
。
它在defaultContext
上返回ImageCD
的实例。
当您更改imageKeyword
的值时,您将在defaultContext
上更改它。不在localContext
中,在saveWithBlock
中可用。
当您的saveWithBlock
完成时,您什么也没有保存!下次defaultContext
将您的更改保存到localImage
时将被保留。
很容易修复。只需在saveWithBlock
中调用findFirstByAttribute
并使用localContext
。当saveWithBlock
完成时,它会将localContext
合并到defaultContext
。
为了安全起见,我会更改您的第一个代码块,以便所有获取和删除都在同一个上下文中:
-(void)updateLocalImagesFromActivitiesParents:(NSArray*)allImageArray
NSPredicate *imageIdsFilter = [NSPredicate predicateWithFormat:@"NOT (imageId IN %@)", allImageArray];
if([imagesToDelete count] > 0)
[MagicalRecord saveWithBlockAndWait:^(NSManagedObjectContext *localContext)
NSFetchRequest *imageIdsRequest = [ImageCD MR_requestAllWithPredicate:(NSPredicate *)imageIdsFilter inContext:localContext];
NSArray *imagesToDelete = [ImageCD MR_executeFetchRequest:imageIdsRequest inContext:localContext];
for(ActivityCD *imageToDelete in imagesToDelete)
[imageToDelete MR_deleteEntityInContext:localContext];
[localContext MR_saveToPersistentStoreAndWait];
];
您可能应该阅读有关 NSManagedObjectContext
的 MagicalRecord 和 Apple 文档。祝你好运!
【讨论】:
以上是关于predicateWithFormat 返回错误的核心数据对象的主要内容,如果未能解决你的问题,请参考以下文章
NSPredicate - predicateWithFormat 不安全
用于电子邮件问题的 NSPredicate predicateWithFormat
如何使用 predicateWithFormat 查询 NSString 包含在 NSSet 中