awakeFromInsertで初期化を実行
MixerCDのawakeFromInsertでやるべき事は、Oscillatorを作成し、それをoscillators対多関連に登録する事とosc1, osc2, osc3関連にセットする事です。よってMixerCDの初期化コードは以下の様になります。
重要事項としてデベロッパドキュメントに載っていますが、サブクラスは自分の初期化コードを実行する前にスーパークラスのawakeFromInsertを呼び出さないといけません。これはawakeFromFetchでも同じです。
//
// MixerCD.m
//
#pragma mark -
#pragma mark Initializer
- (void)createOscillator
{
int i;
OscillatorCD *osc;
for(i=0;i<3;i++)
{
osc = [NSEntityDescription insertNewObjectForEntityForName:@"Oscillator"
inManagedObjectContext:MOC];
[[self mutableSetValueForKey:@"oscillators"] addObject:osc];
if(i==0)
[self setOsc1:osc];
else if(i==1)
[self setOsc2:osc];
else
[self setOsc3:osc];
}
}
- (void)awakeFromInsert
{
[super awakeFromInsert];
[self createOscillator];
}
MasterMotifCDではMixerを生成します。また初期化の最後でfullUpdateを実行します。これでMasterMotif, Mixer, Oscillatorの各bezierPath属性が初期化されます。
//
// MasterMotifCD.m
//
#pragma mark -
#pragma mark Initializer
- (void)createMixer
{
int i;
MixerCD *mixer;
for(i=0;i<2;i++)
{
mixer = [NSEntityDescription insertNewObjectForEntityForName:@"Mixer"
inManagedObjectContext:MOC];
[[self mutableSetValueForKey:@"mixers"] addObject:mixer];
if(i==0)
[self setX:mixer];
else
[self setY:mixer];
}
}
- (void)awakeFromInsert
{
[super awakeFromInsert];
[self createMixer];
[self fullUpdate];
}
awakeFromFetchの謎
その操作とは「EditメニューもしくはHelpメニューを開いて、何もコマンドを実行せずに閉じる事」です。これで何らかの操作が登録されるらしく、ドキュメントがダーティになって、アンドゥメニューが有効になります。アンドゥを実行しても見た目では何も変わらず、何が実行されたのかわかりません。ところがOscillatorCDとMixerCDのawakeFromFetchをコメントアウトすると、アンドゥを実行した時にそれぞれの波形が消えます。リドゥで復活します。
CoreDataフレームワークの内部で一体何が起こっているのでしょうか?謎です。
//
// MixerCD.m
//
- (void)awakeFromFetch
{
[super awakeFromFetch];
[UNDO_MANAGER disableUndoRegistration];
[self updateBezierPath];
[UNDO_MANAGER enableUndoRegistration];
}
//
// MasterMotifCD.m
//
- (void)awakeFromFetch
{
[super awakeFromFetch];
[UNDO_MANAGER disableUndoRegistration];
[self fullUpdate];
[UNDO_MANAGER enableUndoRegistration];
}
対症療法でとりあえず何とかする
そこで対症療法ですが、awakeFromFetchで一度ダミーの操作を実行し、それをアンドゥしてみる事にしました。こんな感じです。
//
// MasterMotifCD.m
//
- (void)awakeFromFetch
{
[super awakeFromFetch];
[UNDO_MANAGER disableUndoRegistration];
[self fullUpdate];
[UNDO_MANAGER enableUndoRegistration];
[self setResolution:[self resolution]];
[UNDO_MANAGER undo];
}
これで謎のアンドゥはできなくなるのですが、リドゥメニューにダミー操作をリドゥする項目が現れてしまっています。
そこでアンドゥマネージャに登録されているアクションをリセットします。
//
// MasterMotifCD.m
//
- (void)awakeFromFetch
{
[super awakeFromFetch];
[UNDO_MANAGER disableUndoRegistration];
[self fullUpdate];
[UNDO_MANAGER enableUndoRegistration];
[self setResolution:[self resolution]];
[UNDO_MANAGER undo];
[UNDO_MANAGER removeAllActions];
}
これでようやく問題が解決しました。ところで、こうなってみるとアンドゥの登録を禁止、有効にしているコードはもう不要ですね。これらを削除します。
//
// MasterMotifCD.m
//
// 「EditメニューもしくはHelpメニューを開いて、何もコマンドを実行せずに閉じる事」で謎のアンドゥが実行できてしまう
// パラメータを変更するなど、一度何らかの操作をアンドゥマネージャに登録すると発生しなくなる
// 対症療法だが、awakeFromFetchで一度ダミーの操作を実行し、それをアンドゥして対策とする
- (void)awakeFromFetch
{
[super awakeFromFetch];
[self fullUpdate];
[self setResolution:[self resolution]];
[UNDO_MANAGER undo];
[UNDO_MANAGER removeAllActions];
}
resolutionに同じ値を設定しているのだからアンドゥしなくても同じではないかと、アンドゥを実行している行も削除したところ、これはうまくいきませんでした。病状が再現します。
やっぱりawakeFromFetchは謎です。

ホーム
前へ