2011-09-11 19 views
4

ここは奇妙なものです。私のアプリケーションは、完了ブロックを引数として、ハードウェアデバイスを制御するオブジェクトにシャットダウンメッセージを送信します。シャットダウンメッセージは、すぐにシャットダウンを完了できたかどうかによって、BOOLを返します。したがって、YESは完了したことを意味し、NOは後で完了時に完了ハンドラを呼び出すことを意味します。ここでObjective-C補完ブロックが余分なメソッド呼び出しを引き起こしますか?

は、メインコントローラのコードです:

- (BOOL)shutdownWithCompletionHandler:(void (^)(void))handler 
{ 
if (busy) 
{ 
    self.completionBlock = handler; 
    [self stopDevice]; 
    NSLog(@"shutdownWithCompletionHandler: Wait for reset"); 
    return NO; 
} 

NSLog(@"Stoker: shutdownWithCompletionHandler: shutdown now"); 
return YES; 
} 

奇妙な部分は、シャットダウンメッセージが2回送信されるということです。

- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender 
{    
BOOL shutdownNow = [theStoker shutdownWithCompletionHandler:^(void) 
{ 
    NSLog(@"applicationShouldTerminate: completionBlock"); 
    [[NSRunningApplication currentApplication] terminate]; 
}]; 

if (!shutdownNow) 
{ 
    NSLog(@"applicationShouldTerminate: waiting for shutdown"); 
    return NSTerminateCancel; 
} 
return NSTerminateNow;   
} 

ここでは、デバイス・コントローラ・コードです。これらはのNSLogメッセージです:

shutdownWithCompletionHandler: Wait for reset 
applicationShouldTerminate: waiting for reset 
applicationShouldTerminate: completionBlock 
shutdownWithCompletionHandler: shutdown now 

だから、完了ブロックを実行した後、私は戻って、デバイスオブジェクトのshutdownWithCompletionHandler:方法で終わります。どうして?

編集:Hmmm。 [[NSRunningApplication currentApplication] terminate];applicationShouldTerminate:を再度呼び出しますか?私はそれが必要だと思います。補完ハンドラでアプリを終了するより良い方法はありますか?

答えて

5

問題の根本的な原因(terminateを呼び出すのはapplicationShouldTerminate:)を見つけたので、これを回避する方法があります。

終了をキャンセルする代わりに、後でシャットダウンするときにNSTerminateLaterを返します。完了ブロックは、applicationShouldTerminate:を再度呼び出すことなく、[NSApp replyToApplicationShouldTerminate:YES]を呼び出して終了をトリガーする必要があります。

- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {    
    BOOL shutdownNow = [theStoker shutdownWithCompletionHandler:^(void) { 
     NSLog(@"applicationShouldTerminate: completionBlock"); 
     [NSApp replyToApplicationShouldTerminate:YES]; 
    }]; 

    if (!shutdownNow) { 
     NSLog(@"applicationShouldTerminate: waiting for shutdown"); 
     return NSTerminateLater; 
    } 
    return NSTerminateNow;   
} 
+0

ありがとうございました! – Flyingdiver

+0

Bummer。これは実際には機能しません。これにより、実行ループがNSModalPanelRunLoopModeに入ります。これは、アプリケーションが実行ループでAsyncSocket呼び出しを取得しないため、デバイスと通信してシャットダウンすることができないことを意味します。私は別の実行ループに移す必要があります。これは、2回目の呼び出しを避ける価値があるよりも多くの作業です。 – Flyingdiver

+0

私は、AsyncSocketのRun LoopバージョンからGCDバージョンに切り替えました。これで、終了が保留されている間にデバイスコントローラコードを完成させることができます。 – Flyingdiver

関連する問題