重要な更新:私の質問の大部分が誤った前提に基づいていることがわかりました(以下の私の答えを参照してください)。通知は実際に受信者に届きましたが、届くのが速すぎました。(ただし、ブレークポイントがある場合とない場合の動作が異なる理由はまだ説明されていません。)
与えられたファイルのハッシュを計算するアプリを開発しています。計算はSHHashComputerで行われます。これは、ファイルパスを取得してNSInvocationOperationを作成する抽象クラスです(Objective Cには抽象クラスがないため、抽象クラスを意図しています)。次に、メソッド(void)computeAndSendHashを呼び出します。このメソッドは、オブジェクトに保存されているファイルパスを使用してハッシュを計算し、通知として送信します。実際の計算は、子クラスがオーバーライドする必要がある(NSString *)computeHashメソッドで行われます。
SHHashComputer.mは次のとおりです。
- (NSString*)computeHash {
return [NSString stringWithFormat:@"unimplemented hash for file %@", self.path];
}
- (void)computeAndSendHash {
NSString *result = [self computeHash];
NSString *notificationName = [NSString stringWithFormat:@"%@%@",
gotResultNotification,
self.hashType];
[[NSNotificationCenter defaultCenter] postNotificationName:notificationName
object:result];
self.operation = nil;
}
そして、これがSHMD5Computer.m(SHHashComputerの子クラス)です。
- (NSString*)computeHash {
return @"MD5 test"; // it actually doesn't matter what it returns
}
通知の受信者に迷惑をかけることはありません。SHMD5Computer.mのcomputeHashメソッドをコメントアウトする限り、すべてが正常に機能するとしましょう。「未実装...」というテキストの通知が受信され、GUIに表示されます。しかし、私がそうしないと、それは本当に興味深いものになります。
ブレークポイントを設定しないと、通知が届きません。ただし、SHMD5Computer.hのcomputeHashの宣言にブレークポイントを設定し、「 self.operation = nil」という行までステップオーバーして、その時点で実行を続けると、通知は宛先に到達します。ここで止まらないと、デバッガーが何もデバッグしていないかのように突然状態に切り替わり、アプリがフリーズします。
「WTF」はここでの質問に適した形式ではないと思うので、このように言いましょう。何かが足りないのでしょうか。コードにエラーがありますか?xcodeでこのタイプの動作を引き起こす原因は何ですか?どうすればこれを修正できますか?
(私のコードをすべて複製してもらいたい場合は、喜んで提供します。)
その他の実験:
ブレークポイントで停止した直後に実行を続行すると、アプリケーションは、通知を受信するコードの最後の行でEXC_BAD_ACCESSエラーを検出します。
id newResult = [newResultNotification object]; if (newResult == nil) [NSException raise:@"No object" format:@"Expected object with notification!"]; else if (![newResult isKindOfClass:[NSString class]]) [NSException raise:@"Not NSString" format:@"Expected NSString object!"]; else self.result = (NSString*) newResult; [self.textField setStringValue:self.result];
前の実験を再現しようとすると、さらに奇妙なことが起こりました。私のデバッグ設定では、2つのハッシュコンピューターオブジェクトがあります。1つはSHMD5HashComputer(これについて話している)で、もう1つはSHHashComputer(もちろん、「実装されていない」ハッシュを生成します)です。以前のすべての実験では、アプリがクラッシュしない限り、SHHashComputerからの通知フォームが常に正常に届きました。ただし、この場合、両方の通知が届かず、アプリはクラッシュしませんでした。(すべての手順は前の手順とまったく同じです)。
- Josh Caswellがコメントで指摘しているように、私は通知を正しく使用していませんでした。ドキュメントで説明されているように、オブジェクト自体を通知オブジェクトとして送信する必要がありました。私はそれを修正しました、そして私はまったく同じ結果を得ています。(これは、通知が正しく機能することがあり、問題がなかったため、正しく修正したことを意味します)。
その他の更新:
送信する通知はSHHashResultViewControllerに到着するはずです。それが私がそれを作成して通知のために登録する方法です:
- (id)initWithHashType:(NSString *)hashType {
self = [self initWithNibName:@"SHHashResultView" bundle:[NSBundle mainBundle]];
if (self) {
[self setHashType:hashType];
}
return self;
}
- (void)setHashType:(NSString *)hashType {
[self.label setStringValue:[NSString stringWithFormat:@"%@:", hashType]];
_hashType = hashType;
NSString *notificationName = [NSString stringWithFormat:@"%@%@",
gotResultNotification,
_hashType];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(gotResult:)
name:notificationName
object:nil];
}