-[NSManagedObject willTurnIntoFault] 是否禁用 KVO 通知?

发布于 2024-10-12 23:54:44 字数 341 浏览 2 评论 0原文

我有一个 NSManagedObject (人),它有几个注册到嵌套非托管属性的观察者(person.address.street,地址是非托管的,即未在核心数据中定义)。当托管对象出现故障时,我调用

person.address = nil

willTurnIntoFault 来清除我的非托管属性。然而,KVO 不会删除其注册地址以获取“街道”更改通知的观察者,尽管地址符合 KVO 标准。地址被释放,我收到一条警告,指出它仍然有观察者注册。

我能弄清楚的唯一原因是 willTurnIntoFault 禁用了 KVO 通知。是这样吗?有解决方法吗?

谢谢, 约亨

I have a NSManagedObject (person) that has several observers registered to a nested unmanaged property (person.address.street, address is unmanaged, i.e. not defined in Core Data). When the managed object gets faulted, I call

person.address = nil

in willTurnIntoFault to clear my unmanaged property. However, KVO does not remove the observers it registered for address to get notified of changes to 'street', although address is KVO compliant. Address gets deallocated, and I get a warning that it still has observers registered to it.

The only reason I can figure out is that willTurnIntoFault disables KVO notifications. Is this the case? Is there a workaround for this.

Thanks,
Jochen

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

Jochen,

我将相同的行为视为托管对象上下文合并处理的一部分(通过 mergeChangesFromContextDidSaveNotification:)。对于合并用户信息中的“更新”对象,核心数据对“本地”上下文的对象进行故障处理,然后针对“远程”上下文的对象执行合并。

如果作为 didTurnIntoFault: 处理的一部分,我释放了我的非托管属性(这非常简单并且绝对符合 KVO),则会出现错误。有趣的是,它似乎只发生在“嵌套”非托管属性中。我有许多其他非托管属性作为托管对象的一部分,这些属性是简单对象(NSNumber、NSString 等),并且这些属性可以作为 didTurnIntoFault: 处理的一部分发布,没有任何问题。只有当在非托管属性中观察到属性 >= 2 层深度时,我才会发现问题。

我不确定您是否已经找到解决方案(我很想听听您在这方面的进展情况),但我已经找到了解决方法。我将在故障对象中分配的非托管属性保留下来,并且仅在prepareForDeletion期间取消分配它。

-(void) performInventoryItemObjectSetup
{
    if ([self unitsManager] == nil) {
        [self setUnitsManager:[[[BTUnitsManager alloc] init] autorelease]];
    }
    ...
}

-(void) performInventoryItemObjectCleanup
{
    ...
}

/********************/

-(void) awakeFromInsert
{
    //NSLog(@"InventoryItem: awakeFromInsert");
    [super awakeFromInsert];
    [self performInventoryItemObjectSetup];
}

-(void) awakeFromSnapshotEvents:(NSSnapshotEventType)flags
{
    //NSLog(@"InventoryItem: awakeFromSnapshotEvents: 0x%lx", flags);

    [super awakeFromSnapshotEvents:flags];

    if (flags & NSSnapshotEventUndoDeletion) {
        [self performInventoryItemObjectSetup];
    }
}

-(void) awakeFromFetch
{
    //NSLog(@"InventoryItem: awakeFromFetch");
    [super awakeFromFetch];
    [self performInventoryItemObjectSetup];
}

-(void) didTurnIntoFault
{
    //NSLog(@"InventoryItem: didTurnIntoFault");
    [self performInventoryItemObjectCleanup];
    [super didTurnIntoFault];
}


-(void) prepareForDeletion
{
    NSLog(@"InventoryItem: prepareForDeletion");
    [self setUnitsManager:nil];
    [super prepareForDeletion];
}

我怀疑越来越多的人会遇到这个问题,因为越来越多的 Core Data 应用程序在 iCloud 支持下发布,这需要这种合并作为 NSPersistentStoreDidImportUbiquitousContentChangesNotification 处理的一部分。要么这样,要么我们会发现我们做错了什么:-)。

干杯,
迈克尔.

Jochen,

I see this same behaviour as part of managed object context merge processing (via mergeChangesFromContextDidSaveNotification:). For "updated" objects in the merge user info, core data faults the "local" context's object and then performs a merge against the "remote" context's object.

If, as part of didTurnIntoFault: handling, I release my unmanaged property (which is very simple and definitely KVO compliant), the error appears. Interestingly, it only seems to happen with "nested" unmanaged properties. I have many other unmanaged properties as part of my managed objects which are simple objects (NSNumber, NSString etc), and these can be released as part of didTurnIntoFault: handling without any issues. It's only when properties >= 2 levels deep are being observed within the unmanaged property that I see the problem.

I'm not sure if you have found a solution or not yet (I'd be very interested in hearing how you've progressed with this), but I have found a work-around. I leave my unmanaged property allocated within the faulted object and only deallocate it during prepareForDeletion.

-(void) performInventoryItemObjectSetup
{
    if ([self unitsManager] == nil) {
        [self setUnitsManager:[[[BTUnitsManager alloc] init] autorelease]];
    }
    ...
}

-(void) performInventoryItemObjectCleanup
{
    ...
}

/********************/

-(void) awakeFromInsert
{
    //NSLog(@"InventoryItem: awakeFromInsert");
    [super awakeFromInsert];
    [self performInventoryItemObjectSetup];
}

-(void) awakeFromSnapshotEvents:(NSSnapshotEventType)flags
{
    //NSLog(@"InventoryItem: awakeFromSnapshotEvents: 0x%lx", flags);

    [super awakeFromSnapshotEvents:flags];

    if (flags & NSSnapshotEventUndoDeletion) {
        [self performInventoryItemObjectSetup];
    }
}

-(void) awakeFromFetch
{
    //NSLog(@"InventoryItem: awakeFromFetch");
    [super awakeFromFetch];
    [self performInventoryItemObjectSetup];
}

-(void) didTurnIntoFault
{
    //NSLog(@"InventoryItem: didTurnIntoFault");
    [self performInventoryItemObjectCleanup];
    [super didTurnIntoFault];
}


-(void) prepareForDeletion
{
    NSLog(@"InventoryItem: prepareForDeletion");
    [self setUnitsManager:nil];
    [super prepareForDeletion];
}

I suspect more people will run into this issue as more and more Core Data apps are released with iCloud support which requires this kind of merging as part of NSPersistentStoreDidImportUbiquitousContentChangesNotification handling. Either that or we'll find out what we're doing wrong :-).

Cheers,
Michael.

思慕 2024-10-19 23:54:44

您可以使用 http://developer.apple 中描述的技术.com/library/mac/#releasenotes/Cocoa/FoundationOlder.html
为了避免此错误,您可以在绑定中使用不同的键路径,其中将包含符合 KVO 的实体。
请参阅“支持调试不良 KVO 合规性”和“修复一种不良 KVO 合规性的建议”说明。

You can using a technic, which describe in http://developer.apple.com/library/mac/#releasenotes/Cocoa/FoundationOlder.html
To avoid this error, u can using a different keypath in binding, which will include entity, with KVO compliant.
Please look to "Support for Debugging of Bad KVO Compliance" and "Advice for Fixing One Kind of Bad KVO Compliance" notes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文