1

親と子の 2 つの NSManagedObject サブクラスがあります。親には、OrderedSet に多くの子 (ren) が含まれています。子の状態が変化したとき、親にそれを知らせたいです。

別の言語でプログラミングしている場合は、イベントを使用して、親がそれぞれの子からのイベントをリッスンするようにしますが、ターゲット アクションがビュー コンポーネントに限定されていることを考えると、Objective C で提供されるのはグローバル NSNotificationCenter の使用だけです。モデルがグローバル通知を利用するという考えは絶対に好きではありません (私の本では、イベントを介して直接リッスンすることは問題ありません)。ただし、2 つの NSManagedObjects の間で委任を使用することは、一方が他方への参照を失わないようにすることが困難であることを考えると、危険な考えのように思えます。

これをどのように処理すべきかについて、誰か提案はありますか?

4

2 に答える 2

2

もう 1 つのオプションは、キー値の観察です。次のように設定します。

const static void *kParentObservingChildSomePropertyContext = &kParentObservingChildSomePropertyContext;

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

スーパークラスまたはサブクラスの観測コンテキストを踏まないように、すべての観測コンテキストが一意である必要があるため、奇妙な定数定義が存在します。どのオプションを設定する必要があるかを確認するには、マニュアルを参照して、特定のニーズと比較してください。子オブジェクトのプロパティが変更されるたびに、親は次を受け取ります。

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

観察の正しいコンテキストがあることを確認してから、変更を処理します。ここで別のコンテキストが表示された場合は、メッセージを に転送してくださいsuper

パスの監視が完了したら、親を子のオブザーバーとして削除します。

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

-addObserver:forKeyPath:options:context観測の正しいインスタンスが削除されるように、使用したのと同じコンテキスト ポインターを使用します。

ただし、2 つの NSManagedObjects 間で委任を使用することは、一方が他方への参照を失わないようにすることが困難であることを考えると、危険な考えのように思えます。

特定のオブジェクトからの通知の委任、監視、および監視はすべて、この問題に悩まされます。通知に関心のある有効期間が、関連するオブジェクトの有効期間と一致することを確認する必要があります。そうしないと、監視情報を簡単に「漏えい」したり、さらに悪いことに、古いオブジェクト ポインターに通知を送信したりする可能性があります。これらの解決策はどれもそれを免れることはできませんが、Delegate パターンの場合、親オブジェクトが消えたときに子がそれ以上委任しようとしないようにするために、弱い参照をゼロにすることを使用できます。

于 2012-05-27T12:08:13.177 に答える
1

リクエストを処理するView Controllerで監視するフィールドを選択します... [self addObserver:self forKeyPath:@"clientProgress.dateLastUpdated" options:0 context:nil];

同じView Controllerで、dealloc(またはARCでdeallocに渡されるもの)でオブザーバーを削除することを確認します。- (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];

}

最後に、オブザーバーを呼び出したいときは、日付を更新するだけです... //変更された日付と前のViewControllerを設定して保存を強制し、呼び出し元のビューコントローラーから保存してリロードします//実行中のオブザーバーがあるためこのキー値を監視 clientProgress.dateLastUpdated = [NSDate date];

于 2012-05-27T12:53:10.097 に答える