如何使用中间模型格式化核心数据多对多谓词
How to format a core data many to many predicate with an intermediate model
我有以下核心数据模型:
我有一个包含特定 SkillGroup 的视图控制器。我想发出一个获取请求,其中包含该技能组中所有技能的记录。通常我会认为它会像
request.predicate = NSPredicate(format: "skill IN %@.skills", skillGroup!)
但是我需要创建中间“SkillGroupItem”模型,以便我可以跟踪 skillGroup 中每个技能的 displayIndex。我在想类似的东西:
request.predicate = NSPredicate(format: "ANY %@.skillGroupItems.skill = skillProgress.skill", skillGroup!)
因此任何 skillGroup 的 skillGroupItems 技能都等于记录 skillProgress object.skill...
但这会引发此错误:
CoreData: annotation: to-many relationship fault "skillGroupItems" for objectID 0xb9291ca50355a7c1 <x-coredata://33325602-3973-46E7-8400-45922DD97A05/SkillGroup/p1> fulfilled from database. Got 1 rows
CoreData: sql: SELECT DISTINCT t0.Z_ENT, t0.Z_PK, t0.Z_OPT, t0.ZRECORDTYPE, t0.ZTIMESTAMP, t0.ZSKILLPROGRESS, t0.ZIMAGEFILENAME, t0.ZTEXT, t0.ZTHUMBNAILFILENAME, t0.ZVIDEOFILENAME FROM ZRECORD t0 JOIN ZSKILLPROGRESS t1 ON t0.ZSKILLPROGRESS = t1.Z_PK WHERE ? = t1.ZSKILL ORDER BY t0.ZTIMESTAMP
2021-04-20 13:37:43.482875-0700 SweatNetOffline[38167:3014868] -[__NSSingleObjectSetI longLongValue]: unrecognized selector sent to instance 0x600002a69360
CoreData: annotation: total fetch execution time: 0.0013s for 0 rows.
2021-04-20 13:37:43.484519-0700 SweatNetOffline[38167:3014868] [error] error: SQLCore dispatchRequest: exception handling request: <NSSQLFetchRequestContext: 0x60000117d5e0> , -[__NSSingleObjectSetI longLongValue]: unrecognized selector sent to instance 0x600002a69360 with userInfo of (null)
CoreData: error: SQLCore dispatchRequest: exception handling request: <NSSQLFetchRequestContext: 0x60000117d5e0> , -[__NSSingleObjectSetI longLongValue]: unrecognized selector sent to instance 0x600002a69360 with userInfo of (null)
2021-04-20 13:37:43.503515-0700 SweatNetOffline[38167:3014868] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSSingleObjectSetI longLongValue]: unrecognized selector sent to instance 0x600002a69360'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff20421af6 __exceptionPreprocess + 242
1 libobjc.A.dylib 0x00007fff20177e78 objc_exception_throw + 48
2 CoreFoundation 0x00007fff204306f7 +[NSObject(NSObject) instanceMethodSignatureForSelector:] + 0
3 CoreFoundation 0x00007fff20426036 ___forwarding___ + 1489
4 CoreFoundation 0x00007fff20428068 _CF_forwarding_prep_0 + 120
5 CoreData 0x00007fff25114346 -[NSSQLiteConnection execute] + 1416
6 CoreData 0x00007fff2538acfa _newFetchedRowsForFetchPlan_ST + 1234
7 CoreData 0x00007fff2537b1c5 _executeFetchRequest + 55
8 CoreData 0x00007fff252cd352 -[NSSQLFetchRequestContext executeRequestCore:] + 41
9 CoreData 0x00007fff253430a3 -[NSSQLStoreRequestContext executeRequestUsingConnection:] + 405
10 CoreData 0x00007fff2531468f __52-[NSSQLDefaultConnectionManager handleStoreRequest:]_block_invoke + 56
11 CoreData 0x00007fff2527bdbd __37-[NSSQLiteConnection performAndWait:]_block_invoke + 28
12 libdispatch.dylib 0x00000001094479c8 _dispatch_client_callout + 8
13 libdispatch.dylib 0x0000000109456bfe _dispatch_lane_barrier_sync_invoke_and_complete + 132
14 CoreData 0x00007fff2527bca3 -[NSSQLiteConnection performAndWait:] + 134
15 CoreData 0x00007fff253145a4 -[NSSQLDefaultConnectionManager handleStoreRequest:] + 273
16 CoreData 0x00007fff2531afd8 -[NSSQLCoreDispatchManager routeStoreRequest:] + 283
17 CoreData 0x00007fff2524b284 -[NSSQLCore dispatchRequest:withRetries:] + 161
18 CoreData 0x00007fff2524681e -[NSSQLCore processFetchRequest:inContext:] + 88
19 CoreData 0x00007fff2511a461 -[NSSQLCore executeRequest:withContext:error:] + 1072
20 CoreData 0x00007fff2522595a __65-[NSPersistentStoreCoordinator executeRequest:withContext:error:]_block_invoke.797 + 3219
21 CoreData 0x00007fff2521e02a -[NSPersistentStoreCoordinator _routeHeavyweightBlock:] + 222
22 CoreData 0x00007fff2511993e -[NSPersistentStoreCoordinator executeRequest:withContext:error:] + 1684
23 CoreData 0x00007fff25117ef2 -[NSManagedObjectContext executeFetchRequest:error:] + 885
24 CoreData 0x00007fff252da7d0 __43-[NSFetchedResultsController performFetch:]_block_invoke + 417
25 CoreData 0x00007fff2514ce63 developerSubmittedBlockToNSManagedObjectContextPerform + 154
26 CoreData 0x00007fff2514cd4a -[NSManagedObjectContext performBlockAndWait:] + 197
27 CoreData 0x00007fff252dcc13 -[NSFetchedResultsController _recursivePerformBlockAndWait:withContext:] + 145
28 CoreData 0x00007fff252da523 -[NSFetchedResultsController performFetch:] + 231
29 SweatNetOffline 0x0000000108ece722 $s15SweatNetOffline22ProgressViewControllerC11viewDidLoadyyF + 1122
30 SweatNetOffline 0x0000000108ecf8db $s15SweatNetOffline22ProgressViewControllerC11viewDidLoadyyFTo + 43
31 UIKitCore 0x00007fff23f5e36e -[UIViewController _sendViewDidLoadWithAppearanceProxyObjectTaggingEnabled] + 88
32 UIKitCore 0x00007fff23f62cd7 -[UIViewController loadViewIfRequired] + 1084
33 UIKitCore 0x00007fff23f630c1 -[UIViewController view] + 27
34 UIKitCore 0x00007fff23e82c37 -[UINavigationController _startCustomTransition:] + 1254
35 UIKitCore 0x00007fff23e991d6 -[UINavigationController _startDeferredTransitionIfNeeded:] + 684
36 UIKitCore 0x00007fff23e9a5e8 -[UINavigationController __viewWillLayoutSubviews] + 150
37 UIKitCore 0x00007fff23e7ad9e -[UILayoutContainerView layoutSubviews] + 217
38 UIKitCore 0x00007fff24bf8504 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2924
39 QuartzCore 0x00007fff27b1bc2b -[CALayer layoutSublayers] + 258
40 QuartzCore 0x00007fff27b2219d _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 575
41 QuartzCore 0x00007fff27b2df3f _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 65
42 QuartzCore 0x00007fff27a6d44c _ZN2CA7Context18commit_transactionEPNS_11TransactionEdPd + 496
43 QuartzCore 0x00007fff27aa4233 _ZN2CA11Transaction6commitEv + 783
44 QuartzCore 0x00007fff27aa53ef _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 79
45 CoreFoundation 0x00007fff2038f1f8 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
46 CoreFoundation 0x00007fff20389a77 __CFRunLoopDoObservers + 547
47 CoreFoundation 0x00007fff2038a01a __CFRunLoopRun + 1113
48 CoreFoundation 0x00007fff203896d6 CFRunLoopRunSpecific + 567
49 GraphicsServices 0x00007fff2c257db3 GSEventRunModal + 139
50 UIKitCore 0x00007fff24696cf7 -[UIApplication _run] + 912
51 UIKitCore 0x00007fff2469bba8 UIApplicationMain + 101
52 SweatNetOffline 0x0000000108e3d9fb main + 75
53 libdyld.dylib 0x00007fff2025a3e9 start + 1
54 ??? 0x0000000000000003 0x0 + 3
)
libc++abi.dylib: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSSingleObjectSetI longLongValue]: unrecognized selector sent to instance 0x600002a69360'
terminating with uncaught exception of type NSException
CoreSimulator 732.18.6 - Device: iPhone 11 (E5E1A675-AA38-45CE-A047-1C5569598381) - Runtime: iOS 14.4 (18D46) - DeviceType: iPhone 11
我被如何在这种情况下使用 ANY 绊倒了。所以任何 skillGroupItems 都有意义.. 但 ANY skillGroup.skillGroupItems.skill 对我来说似乎不好。您不能在 skillGroupItems 数组中查找 .skill。
关于如何完成此任务的任何建议?谢谢
使用您正在获取的实体(在您的例子中,Record
)作为参考点来解析谓词。所以你会使用这个:
request.predicate = NSPredicate(format: "recordType == %@", givenRecordType)
根据属性recordType
创建谓词,
request.predicate = NSPredicate(format: "skillProgress == %@", givenSkillProgressObject)
根据关系 skillProgress
创建谓词(如果 givenSkillProgress
是您已经获取的 SkillProgress
对象)。如果内存中没有SkillProgress
对象,但知道要为其匹配的属性值,则可以使用相应的keypath表达式来引用相关对象的属性,eg:
request.predicate = NSPredicate(format: "skillProgress.isActive == YES")
将获取相关 SkillProgress
对象处于活动状态的那些 Record
对象。您可以通过在关键路径中使用其他元素来继续“遍历”关系树。所以:
request.predicate = NSPredicate(format: "skillProgress.skill.id == %@", givenSkillID)
将获取那些 Record
对象,其相关 SkillProgress
又与 Skill
相关,而 id
属性与 givenSkillID
相匹配。对于 skillGroupItems
关系(在 Skill
实体上),因为它是一对多的,您需要使用“ANY”来指示任何相关对象都应符合您的条件:
request.predicate = NSPredicate(format: "ANY skillProgress.skill.skillGroupItems == %@", givenSkillGroupItem)
然后最后一步是使用 SkillGroupItem
中的 skillGroup
关系来获取从 Record
到 SkillGroup
的完整密钥路径:
request.predicate = NSPredicate(format: "ANY skillProgress.skill.skillGroupItems.skillGroup == %@", givenSkillGroup)
我有以下核心数据模型:
我有一个包含特定 SkillGroup 的视图控制器。我想发出一个获取请求,其中包含该技能组中所有技能的记录。通常我会认为它会像
request.predicate = NSPredicate(format: "skill IN %@.skills", skillGroup!)
但是我需要创建中间“SkillGroupItem”模型,以便我可以跟踪 skillGroup 中每个技能的 displayIndex。我在想类似的东西:
request.predicate = NSPredicate(format: "ANY %@.skillGroupItems.skill = skillProgress.skill", skillGroup!)
因此任何 skillGroup 的 skillGroupItems 技能都等于记录 skillProgress object.skill...
但这会引发此错误:
CoreData: annotation: to-many relationship fault "skillGroupItems" for objectID 0xb9291ca50355a7c1 <x-coredata://33325602-3973-46E7-8400-45922DD97A05/SkillGroup/p1> fulfilled from database. Got 1 rows
CoreData: sql: SELECT DISTINCT t0.Z_ENT, t0.Z_PK, t0.Z_OPT, t0.ZRECORDTYPE, t0.ZTIMESTAMP, t0.ZSKILLPROGRESS, t0.ZIMAGEFILENAME, t0.ZTEXT, t0.ZTHUMBNAILFILENAME, t0.ZVIDEOFILENAME FROM ZRECORD t0 JOIN ZSKILLPROGRESS t1 ON t0.ZSKILLPROGRESS = t1.Z_PK WHERE ? = t1.ZSKILL ORDER BY t0.ZTIMESTAMP
2021-04-20 13:37:43.482875-0700 SweatNetOffline[38167:3014868] -[__NSSingleObjectSetI longLongValue]: unrecognized selector sent to instance 0x600002a69360
CoreData: annotation: total fetch execution time: 0.0013s for 0 rows.
2021-04-20 13:37:43.484519-0700 SweatNetOffline[38167:3014868] [error] error: SQLCore dispatchRequest: exception handling request: <NSSQLFetchRequestContext: 0x60000117d5e0> , -[__NSSingleObjectSetI longLongValue]: unrecognized selector sent to instance 0x600002a69360 with userInfo of (null)
CoreData: error: SQLCore dispatchRequest: exception handling request: <NSSQLFetchRequestContext: 0x60000117d5e0> , -[__NSSingleObjectSetI longLongValue]: unrecognized selector sent to instance 0x600002a69360 with userInfo of (null)
2021-04-20 13:37:43.503515-0700 SweatNetOffline[38167:3014868] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSSingleObjectSetI longLongValue]: unrecognized selector sent to instance 0x600002a69360'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff20421af6 __exceptionPreprocess + 242
1 libobjc.A.dylib 0x00007fff20177e78 objc_exception_throw + 48
2 CoreFoundation 0x00007fff204306f7 +[NSObject(NSObject) instanceMethodSignatureForSelector:] + 0
3 CoreFoundation 0x00007fff20426036 ___forwarding___ + 1489
4 CoreFoundation 0x00007fff20428068 _CF_forwarding_prep_0 + 120
5 CoreData 0x00007fff25114346 -[NSSQLiteConnection execute] + 1416
6 CoreData 0x00007fff2538acfa _newFetchedRowsForFetchPlan_ST + 1234
7 CoreData 0x00007fff2537b1c5 _executeFetchRequest + 55
8 CoreData 0x00007fff252cd352 -[NSSQLFetchRequestContext executeRequestCore:] + 41
9 CoreData 0x00007fff253430a3 -[NSSQLStoreRequestContext executeRequestUsingConnection:] + 405
10 CoreData 0x00007fff2531468f __52-[NSSQLDefaultConnectionManager handleStoreRequest:]_block_invoke + 56
11 CoreData 0x00007fff2527bdbd __37-[NSSQLiteConnection performAndWait:]_block_invoke + 28
12 libdispatch.dylib 0x00000001094479c8 _dispatch_client_callout + 8
13 libdispatch.dylib 0x0000000109456bfe _dispatch_lane_barrier_sync_invoke_and_complete + 132
14 CoreData 0x00007fff2527bca3 -[NSSQLiteConnection performAndWait:] + 134
15 CoreData 0x00007fff253145a4 -[NSSQLDefaultConnectionManager handleStoreRequest:] + 273
16 CoreData 0x00007fff2531afd8 -[NSSQLCoreDispatchManager routeStoreRequest:] + 283
17 CoreData 0x00007fff2524b284 -[NSSQLCore dispatchRequest:withRetries:] + 161
18 CoreData 0x00007fff2524681e -[NSSQLCore processFetchRequest:inContext:] + 88
19 CoreData 0x00007fff2511a461 -[NSSQLCore executeRequest:withContext:error:] + 1072
20 CoreData 0x00007fff2522595a __65-[NSPersistentStoreCoordinator executeRequest:withContext:error:]_block_invoke.797 + 3219
21 CoreData 0x00007fff2521e02a -[NSPersistentStoreCoordinator _routeHeavyweightBlock:] + 222
22 CoreData 0x00007fff2511993e -[NSPersistentStoreCoordinator executeRequest:withContext:error:] + 1684
23 CoreData 0x00007fff25117ef2 -[NSManagedObjectContext executeFetchRequest:error:] + 885
24 CoreData 0x00007fff252da7d0 __43-[NSFetchedResultsController performFetch:]_block_invoke + 417
25 CoreData 0x00007fff2514ce63 developerSubmittedBlockToNSManagedObjectContextPerform + 154
26 CoreData 0x00007fff2514cd4a -[NSManagedObjectContext performBlockAndWait:] + 197
27 CoreData 0x00007fff252dcc13 -[NSFetchedResultsController _recursivePerformBlockAndWait:withContext:] + 145
28 CoreData 0x00007fff252da523 -[NSFetchedResultsController performFetch:] + 231
29 SweatNetOffline 0x0000000108ece722 $s15SweatNetOffline22ProgressViewControllerC11viewDidLoadyyF + 1122
30 SweatNetOffline 0x0000000108ecf8db $s15SweatNetOffline22ProgressViewControllerC11viewDidLoadyyFTo + 43
31 UIKitCore 0x00007fff23f5e36e -[UIViewController _sendViewDidLoadWithAppearanceProxyObjectTaggingEnabled] + 88
32 UIKitCore 0x00007fff23f62cd7 -[UIViewController loadViewIfRequired] + 1084
33 UIKitCore 0x00007fff23f630c1 -[UIViewController view] + 27
34 UIKitCore 0x00007fff23e82c37 -[UINavigationController _startCustomTransition:] + 1254
35 UIKitCore 0x00007fff23e991d6 -[UINavigationController _startDeferredTransitionIfNeeded:] + 684
36 UIKitCore 0x00007fff23e9a5e8 -[UINavigationController __viewWillLayoutSubviews] + 150
37 UIKitCore 0x00007fff23e7ad9e -[UILayoutContainerView layoutSubviews] + 217
38 UIKitCore 0x00007fff24bf8504 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2924
39 QuartzCore 0x00007fff27b1bc2b -[CALayer layoutSublayers] + 258
40 QuartzCore 0x00007fff27b2219d _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 575
41 QuartzCore 0x00007fff27b2df3f _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 65
42 QuartzCore 0x00007fff27a6d44c _ZN2CA7Context18commit_transactionEPNS_11TransactionEdPd + 496
43 QuartzCore 0x00007fff27aa4233 _ZN2CA11Transaction6commitEv + 783
44 QuartzCore 0x00007fff27aa53ef _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 79
45 CoreFoundation 0x00007fff2038f1f8 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
46 CoreFoundation 0x00007fff20389a77 __CFRunLoopDoObservers + 547
47 CoreFoundation 0x00007fff2038a01a __CFRunLoopRun + 1113
48 CoreFoundation 0x00007fff203896d6 CFRunLoopRunSpecific + 567
49 GraphicsServices 0x00007fff2c257db3 GSEventRunModal + 139
50 UIKitCore 0x00007fff24696cf7 -[UIApplication _run] + 912
51 UIKitCore 0x00007fff2469bba8 UIApplicationMain + 101
52 SweatNetOffline 0x0000000108e3d9fb main + 75
53 libdyld.dylib 0x00007fff2025a3e9 start + 1
54 ??? 0x0000000000000003 0x0 + 3
)
libc++abi.dylib: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSSingleObjectSetI longLongValue]: unrecognized selector sent to instance 0x600002a69360'
terminating with uncaught exception of type NSException
CoreSimulator 732.18.6 - Device: iPhone 11 (E5E1A675-AA38-45CE-A047-1C5569598381) - Runtime: iOS 14.4 (18D46) - DeviceType: iPhone 11
我被如何在这种情况下使用 ANY 绊倒了。所以任何 skillGroupItems 都有意义.. 但 ANY skillGroup.skillGroupItems.skill 对我来说似乎不好。您不能在 skillGroupItems 数组中查找 .skill。
关于如何完成此任务的任何建议?谢谢
使用您正在获取的实体(在您的例子中,Record
)作为参考点来解析谓词。所以你会使用这个:
request.predicate = NSPredicate(format: "recordType == %@", givenRecordType)
根据属性recordType
创建谓词,
request.predicate = NSPredicate(format: "skillProgress == %@", givenSkillProgressObject)
根据关系 skillProgress
创建谓词(如果 givenSkillProgress
是您已经获取的 SkillProgress
对象)。如果内存中没有SkillProgress
对象,但知道要为其匹配的属性值,则可以使用相应的keypath表达式来引用相关对象的属性,eg:
request.predicate = NSPredicate(format: "skillProgress.isActive == YES")
将获取相关 SkillProgress
对象处于活动状态的那些 Record
对象。您可以通过在关键路径中使用其他元素来继续“遍历”关系树。所以:
request.predicate = NSPredicate(format: "skillProgress.skill.id == %@", givenSkillID)
将获取那些 Record
对象,其相关 SkillProgress
又与 Skill
相关,而 id
属性与 givenSkillID
相匹配。对于 skillGroupItems
关系(在 Skill
实体上),因为它是一对多的,您需要使用“ANY”来指示任何相关对象都应符合您的条件:
request.predicate = NSPredicate(format: "ANY skillProgress.skill.skillGroupItems == %@", givenSkillGroupItem)
然后最后一步是使用 SkillGroupItem
中的 skillGroup
关系来获取从 Record
到 SkillGroup
的完整密钥路径:
request.predicate = NSPredicate(format: "ANY skillProgress.skill.skillGroupItems.skillGroup == %@", givenSkillGroup)