0

誰かがこれを以前に見たことがあると思いますが、おそらく明らかな何かが欠けています...簡単な要約を次に示します。CoreDataアプリがあり、CarとCarMileageがあり、より正確には車の旅と考えられています(Car < ->> CarMileage)。CarMileageには、マイレージ(float、旅行の長さ)、forWork(BOOL)などのいくつかの属性が含まれています。mileageForWorkを含むカスタムCarMileageクラスを作成しました(float、forWork = YESの場合はマイレージを返し、forWork = NOの場合は0を返します)。また、+keyPathsForValuesAffectingMileageForWorkがマイレージとforWorkのセットを返すようにしました。次に、その年の特定の車の合計percentMileageForWorkを計算する必要があります。

現在私はCarMileageにいます:

- (float) mileageForWork {
    float mileageForWork;
    if ([self.forWork boolValue] == YES) {
        mileageForWork = [self.mileage floatValue];
    } else {
        mileageForWork = 0;
    }
    [[NSNotificationCenter defaultCenter] postNotificationName: @"mileageForWorkChanged" object:self];
    NSLog(@"send notification");
    return mileageForWork;
}

それから車は持っています:

- (void) awakeFromFetch {
    [super awakeFromFetch];
    [self updatePercentMileageForWork];
    [[NSNotificationCenter defaultCenter] addObserver: self
                                             selector: @selector(updatePercentMileageForWork)
                                                 name: @"mileageForWorkChanged"
                                               object: nil];
    NSLog(@"awakeFromFetch");
}

- (void) awakeFromInsert {
    [super awakeFromInsert];
    [[NSNotificationCenter defaultCenter] addObserver: self
                                             selector: @selector(updatePercentMileageForWork)
                                                 name: @"mileageForWorkChanged"
                                               object: nil];
    NSLog(@"awakeFromInsert");
}

自動保存されたファイルがロードされると、CarおよびCarMileage用のNSArrayControllerを含むVehiclesセクションに移動します。ログには、「通知の送信」、percentMileageForWorkの値、および「awakeFromFetch」が表示され、プログラムが一時停止し、XCodeのスレッドタブがszone_malloc_should_clear、EXC_BAD_ACCESSコード=2でポップアップ表示されます。

なぜこれが起こっているのか、私は完全に迷っています。私の経験の浅い目には、問題は通知をどこで観察すべきかということです。結局のところ、投稿はログになります。なぜクラッシュするのか、何か考えはありますか?

編集(10月14日) -CarMileageの-awakeFromInsertおよびで、オブジェクトがそれ自体のオブザーバーとしてCarを追加するように、キー値監視モデルに変更しようとしました。-awakeFromFetchこれはフェッチでは期待どおりに機能しますが、オブジェクトが挿入されると、-updatePercentMileageForWorkメソッドは起動しません。オブザーバーが追加されたときに、CarとCarMileageの関係がまだ設定されていないためと思われます(したがって、実際にはオブザーバーはまったく設定されていません)。移動する方法があると思います-addObserver:forKeyPath:options:context新しいCarMileageオブジェクトをリレーションシップセットに追加するメソッド内でCarを呼び出すので、その問題は発生しません。おそらく高度に最適化されているCoreDataの独自のコードをいじるべきかどうかわからないだけでなく、そのコードがどのように正常に読み取られるのかわからないため、関係を完全に台無しにすることを心配しています。「mogenerator」について聞いたことがありますが、ドキュメントが見つからず、すでに混乱しているときによくわからない別のプログラムを使用するのは少し不快です...

誰かが私がどこ-addObserver:forKeyPath:options:contextから電話をかけるべきか知っていますか、そしてそれが関係が設定されている場所からであるならば、私はそれをどのように行うでしょうか?または、通知を使用して、これを意図した元の方法で行うにはどうすればよいですか?

4

1 に答える 1

0

愚かな、愚かな私。私の-updatePercentMileageForWorkメソッドはcarMileage。@sum.mileageForWorkを呼び出していました。これにより、再計算されたという新しい通知が送信され、無限ループが設定されました。そこで、CarMileage-mileageForWorkメソッドを次のように変更しました。

- (float) mileageForWork {
    float newMileageForWork;
    if ([self.forWork boolValue] == YES) {
        newMileageForWork = [self.mileage floatValue];
    } else {
        newMileageForWork = 0;
    }

    if (newMileageForWork == mileageForWork) {
        return mileageForWork;
    } else {
        mileageForWork = newMileageForWork;
        [[NSNotificationCenter defaultCenter] postNotificationName: @"mileageForWorkChanged" object:self];
        NSLog(@"send notification");
        return mileageForWork;
    }

}

そうすれば、通知は、毎回ではなく、実際に新しい値である場合にのみ送信されます。そのため、もう1つの問題が残りました。それは、その車に新しいCarMileageオブジェクト(つまり、新しい旅行)が追加されると、mileageForWorkとnewMileageForWorkの両方がデフォルトで0になるため、通知が送信されないことです。mileageForWork = 1でCarMileageの-awakeFromInsertをオーバーライドすると、すべてが機能しますが、新しいオブジェクトが挿入されたときに通知ループが2回実行されることを意味します。ただし、NSManagedObjectContextObjectsDidChangeNotificationを使用する場合のように、特定のループを2回実行する方が、オブジェクトが変更されるたびに通知を送信するよりも効率的であるように思われます。

于 2012-10-20T15:59:04.900 に答える