English 中文(简体)
页: 1 核心数据在利用生成的用户清除物体时断裂
原标题:iOS Core Data to-many relationship breaks when removing an object using the generated accessors

我有一台SOS 4+电器,目前正在改装,以使用核心数据。 我有一个实体“条款”,与另一个实体“MediaResource”有着去管理的关系,我生成了NS管理。 每一组目标次。 这种关系被称为“媒体”,是任择性的,并逐渐删除相关的媒体参考资料。 反之,该条背后。

The generated code included a property of type NSSet * media in the Article class, as well as these methods:

- (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];
}

There are no NSMutableSets here anywhere, but I assume the auto-generated code knows what it is doing.

I can add an article, then add a MediaResource object to it, and do it like this:

            [newArticle addMediaObject:newMediaObject];

I gather from the docs that is the correct way. However, I also see reference to using mutableSetValueForKey: but that does not seem to apply here.

Basically, what happens is that the during a given run, I can add an article, then remove it, and it works fine. However, if I then add it, quit the app then re-run it, then remove it, I get an exception where it is telling an NSSet to remove an object, which of course it can t do. As I didn t actually write these methods, I am confused. Any ideas? Here is the relevant stack trace:

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
最佳回答

Your problem isn t being caused by the autogenerated code. You don t see a mutable set because Core Data actually uses a class cluster for NSSet and returns anther class _NSFaultingMutableSet when a to-many relationship is accessed. The NSSet is most likely used in the header to keep other classes from attempting to set the relationship without using the defined methods.

我有一套生成的类别<代码>。 阿尔法·的建立,与代同关系。 如果我对这一方法的第一行作一个分点:

-(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];
}

... I can then do this at the debugger prompt:

(gdb) po [self primitiveValueForKey:@"betas"]
Relationship objects for {(
)} on 0x4d45e20
(gdb) po [[self primitiveValueForKey:@"betas"] class]
_NSFaultingMutableSet

So, despite the header, the property is a mutable set albeit a custom one.

Likewise, with the matching method:

- (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];
}

... after a save, the debugger gives:

(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

This behind the scenes change in class happens because of the @dynamic processor directive for betas i.e. @dynamic betas; and if that line gets removed, then the attributes will be defined purely as they are in the header.

Check the Article.m file for @dynamic media; If it is missing or is @synthesize media; that is the source of your problem.

问题回答

暂无回答




相关问题
List Contents of Directory in a UITableView

I am trying to list the contents of Ringtones directory in a TableView, however, I am only getting the last file in the directory in ALL cells, instead of file per cell. This is my code: - (...

iPhone NSUserDefaults persistance difficulty

In my app i have a bunch of data i store in the NSUserdefaults. This information consists of an NSObject (Object1) with NSStrings and NSNumbers and also 2 instances of yet another object (Object2). ...

Writing a masked image to disk as a PNG file

Basically I m downloading images off of a webserver and then caching them to the disk, but before I do so I want to mask them. I m using the masking code everyone seems to point at which can be found ...

Resize UIImage with aspect ratio?

I m using this code to resize an image on the iPhone: CGRect screenRect = CGRectMake(0, 0, 320.0, 480.0); UIGraphicsBeginImageContext(screenRect.size); [value drawInRect:screenRect blendMode:...

Allowing interaction with a UIView under another UIView

Is there a simple way of allowing interaction with a button in a UIView that lies under another UIView - where there are no actual objects from the top UIView on top of the button? For instance, ...