gpt4 book ai didi

objective-c - CoreData 是否允许对象图循环? (奇怪的错误)

转载 作者:行者123 更新时间:2023-11-28 19:24:09 24 4
gpt4 key购买 nike

一段时间以来,我一直遇到 CoreData 的奇怪问题。这将是一个冗长的问题,所以请耐心等待...

我有两个实体,称它们为 A 和 B。B 可能既是多个 A 的创建者又是更新者。 A 必须有一个 B 作为创建者,并且可能有也可能没有 B 作为更新者。 (必需和可选的关系。)

B 可能同时创建和更新了零个或多个 A。

With inverse relationships

以上是我搭建的数据模型。 (我真的不需要从 B 到 A 的反比关系,但 CoreData 否则会给我编译时警告。)

编辑

以下是 ManagedObject 子类的相关部分:

啊啊

@property (nonatomic, retain) B * creator;
@property (nonatomic, retain) B * updater;

上午

@dynamic creator;
@dynamic updater;

B.h

@property (nonatomic, retain) NSSet * created;
@property (nonatomic, retain) NSSet * updated;

B.m

@dynamic updated;
@dynamic created;

- (void)addUpdatedObject:(A *)value { NSSet *changedObjects = [[NSSet
alloc] initWithObjects:&value count:1]; [self
willChangeValueForKey:@"updated"
withSetMutation:NSKeyValueUnionSetMutation
usingObjects:changedObjects]; [[self
primitiveValueForKey:@"updated"] addObject:value]; [self
didChangeValueForKey:@"updated"
withSetMutation:NSKeyValueUnionSetMutation
usingObjects:changedObjects]; [changedObjects release]; }

- (void)removeUpdatedObject:(A *)value { NSSet *changedObjects =
[[NSSet alloc] initWithObjects:&value count:1]; [self
willChangeValueForKey:@"updated"
withSetMutation:NSKeyValueMinusSetMutation
usingObjects:changedObjects]; [[self
primitiveValueForKey:@"updated"] removeObject:value]; [self
didChangeValueForKey:@"updated"
withSetMutation:NSKeyValueMinusSetMutation
usingObjects:changedObjects]; [changedObjects release]; }

- (void)addUpdated:(NSSet *)value { [self
willChangeValueForKey:@"updated"
withSetMutation:NSKeyValueUnionSetMutation usingObjects:value];
[[self primitiveValueForKey:@"updated"] unionSet:value]; [self
didChangeValueForKey:@"updated"
withSetMutation:NSKeyValueUnionSetMutation usingObjects:value]; }

- (void)removeUpdated:(NSSet *)value { [self
willChangeValueForKey:@"updated"
withSetMutation:NSKeyValueMinusSetMutation usingObjects:value];
[[self primitiveValueForKey:@"updated"] minusSet:value]; [self
didChangeValueForKey:@"updated"
withSetMutation:NSKeyValueMinusSetMutation usingObjects:value]; }

- (void)addCreatedObject:(A *)value { NSSet *changedObjects = [[NSSet
alloc] initWithObjects:&value count:1]; [self
willChangeValueForKey:@"created"
withSetMutation:NSKeyValueUnionSetMutation
usingObjects:changedObjects]; [[self
primitiveValueForKey:@"created"] addObject:value]; [self
didChangeValueForKey:@"created"
withSetMutation:NSKeyValueUnionSetMutation
usingObjects:changedObjects]; [changedObjects release]; }

- (void)removeCreatedObject:(A *)value { NSSet *changedObjects =
[[NSSet alloc] initWithObjects:&value count:1]; [self
willChangeValueForKey:@"created"
withSetMutation:NSKeyValueMinusSetMutation
usingObjects:changedObjects]; [[self
primitiveValueForKey:@"created"] removeObject:value]; [self
didChangeValueForKey:@"created"
withSetMutation:NSKeyValueMinusSetMutation
usingObjects:changedObjects]; [changedObjects release]; }

- (void)addCreated:(NSSet *)value { [self
willChangeValueForKey:@"created"
withSetMutation:NSKeyValueUnionSetMutation usingObjects:value];
[[self primitiveValueForKey:@"created"] unionSet:value]; [self
didChangeValueForKey:@"created"
withSetMutation:NSKeyValueUnionSetMutation usingObjects:value]; }

- (void)removeCreated:(NSSet *)value { [self
willChangeValueForKey:@"created"
withSetMutation:NSKeyValueMinusSetMutation usingObjects:value];
[[self primitiveValueForKey:@"created"] minusSet:value]; [self
didChangeValueForKey:@"created"
withSetMutation:NSKeyValueMinusSetMutation usingObjects:value]; }

结束编辑

当我创建一个以 B 作为创建者的新 A 时,一切都很好(使用反向关系时)。但是,当我稍后更新同一个 A 时,使用与创建者相同的 B,我遇到以下崩溃:

2011-05-05 13:17:40.885 myapp[27033:207] -[NSCFNumber count]:
unrecognized selector sent to instance 0x5d14eb0

2011-05-05 13:17:40.887 myapp[27033:207] *** Terminating app due to
uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFNumber
count]: unrecognized selector sent to instance
0x5d14eb0'

*** Call stack at first throw: (

0 CoreFoundation 0x014065a9
__exceptionPreprocess + 185


1 libobjc.A.dylib 0x0155a313 objc_exception_throw + 44

2 CoreFoundation 0x014080bb -[NSObject(NSObject)
doesNotRecognizeSelector:] + 187

3 CoreFoundation 0x01377966 ___forwarding___ + 966

4 CoreFoundation 0x01377522 _CF_forwarding_prep_0 + 50

5 CoreFoundation 0x013b7c3b -[NSSet intersectsSet:] + 59

6 Foundation 0x00c3f4fb NSKeyValueWillChangeBySetMutation +
422

7 Foundation 0x00c0416d NSKeyValueWillChange + 400

8 Foundation 0x00c3f34d
-[NSObject(NSKeyValueObserverNotification)
willChangeValueForKey:withSetMutation:usingObjects:] + 315

9 CoreData 0x01172bd0 -[NSManagedObject
willChangeValueForKey:withSetMutation:usingObjects:] + 112

10 myapp 0x0004fd48 -[B addUpdatedObject:] + 168

11 CoreData 0x011729f2 -[NSManagedObject(_NSInternalMethods)
_includeObject:intoPropertyWithKey:andIndex:] + 98

12 CoreData 0x01169301 -[NSManagedObject(_NSInternalMethods)
_didChangeValue:forRelationship:named:withInverse:] + 497

13 Foundation 0x00c051e4 NSKeyValueNotifyObserver + 361

14 Foundation 0x00c04ca6 NSKeyValueDidChange + 384

15 Foundation 0x00beb3e2
-[NSObject(NSKeyValueObserverNotification)
didChangeValueForKey:] + 123

16 CoreData 0x01166adb
_PF_ManagedObject_DidChangeValueForKeyIndex + 171

17 CoreData 0x01165de9 _sharedIMPL_setvfk_core + 313

18 CoreData 0x01173997 _svfk_11 + 39

(是的,B 定义了方法 addUpdatedObject。)

对于进一步的背景,A:s 的列表显示在由 NSFetchedResultsController 支持的 UITableView 中。

最奇怪的是,恕我直言,完全有可能添加一个具有相反关系的新 A(以 B 作为创建者)而不会导致崩溃,同时将相同的 B 作为更新程序添加到同一个 A 会导致碰撞。

但是,当我删除反向关系时,一切都按预期进行。

Without inverse relationships

我可以毫无问题地添加与 A:s 的创建者和更新者相同的 B,并且该应用程序正常运行,除了来自 CoreData 的构建时警告:

A.creator should have an inverse
A.updater should have an inverse

那么,是否有任何 CoreData 大师可以解释第一个案例失败的原因?

最佳答案

你不应该能够建立双重关系。 Xcode 3.x 和更早版本甚至不允许您创建具有双重关系的模型(现在用 Xcode 4 检查一下,看起来它会让您在没有警告的情况下这样做。这不是个好主意。)

强烈不建议使用双重关系,因为它们会给图的完整性带来严重的风险,例如删除规则,如果您在一个关系上有 delete 规则,而在另一个关系上有 deny 规则,会发生什么情况?我认为具有双重关系的图只是等待发生的火车残骸。

更重要的是,我从未见过真正需要这种数据模型的情况。通常,更好的数据模型设计将避免对这种危险设置的明显需求。在这种情况下,我认为您需要插入实体来为实际关系本身建模,因为这些关系实际上具有行为或种类:

A{
creator<-->Creation.a
updater<-->Update.a
}

B{
creations<-->>Creation.b
updates<-->>Update.b
}

Creation{
a<-->A.creator
b<-->>B.cretions
}

Update{
a<-->A.updater
b<<-->B.updates
}

这还可以让您通过向 Update 实体添加属性轻松地对更新日期等内容进行建模。

关于objective-c - CoreData 是否允许对象图循环? (奇怪的错误),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5897447/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com