简体   繁体   English

模型间/ NSManagedObject通信

[英]Inter-Model/NSManagedObject communication

I have two NSManagedObject subclasses: Parent and Child. 我有两个NSManagedObject子类:Parent和Child。 Parent contains many Child(ren) in an OrderedSet. Parent在OrderedSet中包含许多Child(ren)。 When state changes in a Child I want the parent to know about it. 当孩子的状态发生变化时,我希望父母知道它。

If I was programming in another language I might use events, having the Parent listening for events from each of its children, however given that target-action is limited to view components, all Objective C offers me is use of a global NSNotificationCenter. 如果我使用其他语言进行编程,我可能会使用事件,让父母监听来自每个孩子的事件,但是鉴于目标操作仅限于查看组件,所有Objective C都提供给我使用全局NSNotificationCenter。 I definitely don't like the idea of a Model tapping into global notifications (listening directly via events is Ok in my book), so it seems my only alternative is Delegation. 我绝对不喜欢使用模型进入全局通知的想法(直接通过事件直接监听我的书中的确定),所以看来我唯一的选择是委托。 However using delegation between two NSManagedObjects seems like a dangerous idea, given the difficulty in ensuring one party does not lose its reference to the other. 然而,在两个NSManagedObjects之间使用委托似乎是一个危险的想法,因为很难确保一方不会丢失对另一方的引用。

Does anyone have any suggestions as to how I should be handling this? 有没有人对我应该如何处理这个有任何建议?

Another option is key-value observing. 另一种选择是键值观察。 Set it up like this: 设置如下:

const static void *kParentObservingChildSomePropertyContext = &kParentObservingChildSomePropertyContext;

[child addObserver: child.parent forKeyPath: @"someProperty" options: /*see below*/ context: kParentObservingChildSomePropertyContext];

the weird constant definition exists because every observing context should be unique so that you don't tread on superclass or subclass observation contexts. 存在奇怪的常量定义,因为每个观察上下文都应该是唯一的,这样你就不会踩到超类或子类观察上下文。 To see what options you need to set, consult the manual and compare with your specific needs. 要查看需要设置的选项, 请参阅手册并与您的具体需求进行比较。 Now whenever that property on your child object changes, your parent will receive: 现在,只要您的子对象上的该属性发生更改,您的父级将会收到:

-(void)observeValueForKeyPath: (NSString *)path ofObject: (id)object change: (NSDictionary *)change context: (void *)context;

Check that you have the correct context for your observation, then handle the change. 检查您是否具有正确观察背景,然后处理更改。 If you get a different context here, forward the message to super . 如果您在此处获得不同的上下文,请将消息转发给super

When you're done observing the path, you remove the parent as an observer of the child: 当您完成观察路径时,您将父项删除为子项的观察者:

[child removeObserver: child.parent forKeyPath: @"someProperty" context: kParentObservingChildSomePropertyContext];

Use the same context pointer you used in -addObserver:forKeyPath:options:context so that the correct instance of the observation is removed. 使用在-addObserver:forKeyPath:options:context使用的相同上下文指针-addObserver:forKeyPath:options:context以便删除正确的观察实例。

However using delegation between two NSManagedObjects seems like a dangerous idea, given the difficulty in ensuring one party does not lose its reference to the other. 然而,在两个NSManagedObjects之间使用委托似乎是一个危险的想法,因为很难确保一方不会丢失对另一方的引用。

Delegating, observing and watching for notifications from specific objects all suffer from this problem. 委派,观察和观察来自特定对象的通知都会遇到这个问题。 You need to make sure that the lifetime of your interest in the notifications matches the lifetimes of the objects involved, otherwise you could easily "leak" observation info or - and this is worse - send notifications to stale object pointers. 您需要确保您对通知感兴趣的生命周期与所涉及对象的生命周期相匹配,否则您可能很容易“泄漏”观察信息或 - 这更糟糕 - 将通知发送到过时的对象指针。 None of these solutions is immune to that, though in the case of the Delegate pattern you can use a zeroing weak reference to ensure that when the parent object disappears, the child will no longer try to delegate to it. 这些解决方案都不具备这一点,但在Delegate模式的情况下,您可以使用归零弱引用来确保当父对象消失时,子进程将不再尝试委托它。

I pick a field to watch in the view controller that will service the request... [self addObserver:self forKeyPath:@"clientProgress.dateLastUpdated" options:0 context:nil]; 我在视图控制器中选择一个字段来监视请求... [self addObserver:self forKeyPath:@“clientProgress.dateLastUpdated”options:0 context:nil];

I make sure in that same view controller that I remove the observer on dealloc (or whatever passes for dealloc in ARC). 我确保在相同的视图控制器中删除dealloc上的观察者(或者在ARC中的dealloc的任何传递)。 - (void)dealloc { [self removeObserver:self forKeyPath:@"clientProgress.dateLastUpdated"]; - (void)dealloc {[self removeObserver:self forKeyPath:@“clientProgress.dateLastUpdated”]; } }

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqual:@"clientProgress.dateLastUpdated"]) {
    // If this key path has changed, the browser needs to update its display.
    NSError *error = nil;
    if (![managedObjectContext save:&error]) {
        UIAlertView *dialog = [[UIAlertView alloc] initWithTitle:@"Save Error" message:@"Error saving inserted record, contact Tech Support" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil];
        [dialog show];
        [dialog release];
        exit(-1);  // Fail
    }
    if ( changeIsComingFromLibraryInsert ) {

    }
    [conditioningTableView reloadData];
}
// Essential to call super class implementation - NSArrayController relies heavily on KVO
//[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];

} }

Finally, when I want to call the observer, I merely update the date... // force a save by setting the modified date and the preceeding ViewController with then save and reload from the calling view controller // as there is an observer running watching this key value clientProgress.dateLastUpdated = [NSDate date]; 最后,当我想调用观察者时,我只是更新日期... //通过设置修改日期和前面的ViewController强制保存,然后从调用视图控制器保存并重新加载//因为有一个观察者正在运行看这个关键值clientProgress.dateLastUpdated = [NSDate date];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM