我有一个iOS 4 +应用程序,现在正在改装以使用Core Data。我有一个实体“文章”,它与另一个实体“MediaResource”有很多关系,我为每个实体生成了NSManagedObject子类。该关系称为“media”并设置为可选,并且Cascade删除关联的MediaResource对象。该条款有一个反向的反对。
生成的代码包含Article类中NSSet * media类型的属性,以及这些方法:
- (void)addMediaObject:(MediaResource *)value {
NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
[self willChangeValueForKey:@"media" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
[[self primitiveValueForKey:@"media"] addObject:value];
[self didChangeValueForKey:@"media" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
[changedObjects release];
}
- (void)removeMediaObject:(MediaResource *)value {
NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
[self willChangeValueForKey:@"media" withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects];
[[self primitiveValueForKey:@"media"] removeObject:value];
[self didChangeValueForKey:@"media" withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects];
[changedObjects release];
}
- (void)addMedia:(NSSet *)value {
[self willChangeValueForKey:@"media" withSetMutation:NSKeyValueUnionSetMutation usingObjects:value];
[[self primitiveValueForKey:@"media"] unionSet:value];
[self didChangeValueForKey:@"media" withSetMutation:NSKeyValueUnionSetMutation usingObjects:value];
}
- (void)removeMedia:(NSSet *)value {
[self willChangeValueForKey:@"media" withSetMutation:NSKeyValueMinusSetMutation usingObjects:value];
[[self primitiveValueForKey:@"media"] minusSet:value];
[self didChangeValueForKey:@"media" withSetMutation:NSKeyValueMinusSetMutation usingObjects:value];
}
这里没有NSMutableSets,但我认为自动生成的代码知道它在做什么。
我可以添加一篇文章,然后添加一个MediaResource对象,并按照以下方式执行:
[newArticle addMediaObject:newMediaObject];
我从文档中收集到正确的方法。但是,我也看到了使用mutableSetValueForKey:
的参考,但这似乎不适用于此。
基本上,会发生的是,在给定的运行期间,我可以添加一篇文章,然后将其删除,并且它可以正常工作。但是,如果我然后添加它,退出应用程序然后重新运行它,然后删除它,我得到一个异常,它告诉NSSet删除一个对象,当然这是不能做的。由于我实际上没有写这些方法,我很困惑。有任何想法吗?这是相关的堆栈跟踪:
2011-08-16 11:12:32.141 MyApp[41825:207] -[__NSSet0 removeObject:]: unrecognized selector sent to instance 0x8041f60
2011-08-16 11:12:32.144 MyApp[41825:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSSet0 removeObject:]: unrecognized selector sent to instance 0x8041f60'
*** Call stack at first throw:
(
0 CoreFoundation 0x01a5b5a9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x01baf313 objc_exception_throw + 44
2 CoreFoundation 0x01a5d0bb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
3 CoreFoundation 0x019cc966 ___forwarding___ + 966
4 CoreFoundation 0x019cc522 _CF_forwarding_prep_0 + 50
5 CTKennedy 0x000b292c -[Article removeMediaObject:] + 220
6 CoreData 0x0054a1f2 -[NSManagedObject(_NSInternalMethods) _excludeObject:fromPropertyWithKey:andIndex:] + 98
7 CoreData 0x0053f7d1 -[NSManagedObject(_NSInternalMethods) _maintainInverseRelationship:forProperty:oldDestination:newDestination:] + 449
8 CoreData 0x00593b55 -[NSManagedObject(_NSInternalMethods) _propagateDelete:] + 1541
9 CoreData 0x0054a02a -[NSManagedObject(_NSInternalMethods) _propagateDelete] + 42
10 CoreData 0x00549e53 -[NSManagedObjectContext(_NSInternalChangeProcessing) _propagateDeletesUsingTable:] + 515
11 CoreData 0x00549c12 -[NSManagedObjectContext(_NSInternalChangeProcessing) _processDeletedObjects:] + 146
12 CoreData 0x0053cba8 -[NSManagedObjectContext(_NSInternalChangeProcessing) _propagatePendingDeletesAtEndOfEvent:] + 104
13 CoreData 0x00508982 -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] + 754
14 CoreData 0x00542715 -[NSManagedObjectContext save:] + 149
答案 0 :(得分:3)
您的问题不是由自动生成的代码引起的。您没有看到可变集,因为Core Data实际上为NSSet使用了类集群,并在访问了多对多关系时返回了anther类_NSFaultingMutableSet
。 NSSet很可能在头文件中使用,以防止其他类在不使用已定义的方法的情况下尝试设置关系。
我有一个生成的类Alpha
设置,其中包含与betas
类的多对多关系Beta
。如果我在这个方法的第一行放置一个断点:
-(void)addBetasObject:(NSManagedObject *)value {
NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
[self willChangeValueForKey:@"betas" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
[[self primitiveValueForKey:@"betas"] addObject:value];
[self didChangeValueForKey:@"betas" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
[changedObjects release];
}
...我可以在调试器提示符下执行此操作:
(gdb) po [self primitiveValueForKey:@"betas"]
Relationship objects for {(
)} on 0x4d45e20
(gdb) po [[self primitiveValueForKey:@"betas"] class]
_NSFaultingMutableSet
因此,尽管有标题,但该属性是一个可变集,尽管是自定义集。
同样,使用匹配方法:
- (void)removeBetasObject:(NSManagedObject *)value {
NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
[self willChangeValueForKey:@"betas" withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects];
[[self primitiveValueForKey:@"betas"] removeObject:value];
[self didChangeValueForKey:@"betas" withSetMutation:NSKeyValueMinusSetMutation usingObjects:changedObjects];
[changedObjects release];
}
...保存后,调试器给出:
(gdb) po [self primitiveValueForKey:@"betas"]
Relationship objects for {(
<Beta: 0x4d4be40> (entity: Beta; id: 0x4d52510 <x-coredata://64E86DEC-53DA-4197-B1F3-6C0007576100/Beta/p1> ; data: {
alphas = (
"0x4d52140 <x-coredata://64E86DEC-53DA-4197-B1F3-6C0007576100/Alpha/p1>"
);
num = 0;
})
)} on 0x4d45e20
(gdb) po [[self primitiveValueForKey:@"betas"] class]
_NSFaultingMutableSet
这种幕后变化是因为@dynamic
betas
的{{1}}处理器指令,即@dynamic betas;
,如果该行被删除,那么属性将完全按原样定义在标题中。
检查Article.m
@dynamic media;
文件中的@synthesize media;
如果文件丢失或{{1}}是您问题的根源。