2010-01-26 109 views
4

我卡住了!帶塊完成處理程序的自定義模態窗口

我想創建一個自定義模式對話框。我希望它使用塊作爲完成處理程序與NSSavePanel類似地執行。

我只複製了我認爲需要的重要片段。

@implementation ModalWindowController 
    - (void)makeKeyAndOrderFront:(id)sender 
        modalToWindow:(NSWindow*)window 
         sourceRect:(NSRect)rect 
       completionHandler:(void (^)(NSInteger result))handler { 

     _handler = [handler retain]; 

     session = [NSApp beginModalSessionForWindow:[self window]]; 
     [[NSApplication sharedApplication] runModalSession:session]; 

     [[self window] makeKeyAndOrderFrontCentered:self expandingFromFrame:rect]; 
    } 
    - (IBAction)okButtonPressed:(id)sender { 
     [[self window] orderOut:self]; 
     _handler(NSOKButton); 
     [NSApp endModalSession:session]; 
    } 

@end 

現在,我可以把這個使用的代碼:

[self.modalWindowController makeKeyAndOrderFront:self 
            modalToWindow:[[self view] window] 
             sourceRect:sr 
           completionHandler:^(NSInteger result) { 
    NSLog(@"Inside Block"); 
    if (result == NSOKButton) { 
     // do something interesting here 
    } 
}]; 
NSLog(@"Errg"); 

一切順利然而,該方法makeKeyAndOrderFront後:modalToWindow:sourceRect:completionHandler:已完成它不會阻塞線程,因此「即使用戶未選擇「確定」或「取消」,也會打印「錯誤」。此時將顯示模態窗口,用戶單擊確定,然後執行_handler塊。但是,如果我試圖訪問塊中的局部變量,並且應用程序崩潰,因爲已經清理了所有內容。

什麼是從makeKeyAndOrderFront阻止主線程的最佳方法:...方法?這是使用塊實現完成處理程序的正確方法嗎?

回答

5

你行

_handler=[handler retain]; 

應該

_handler=[handler copy]; 

這應該解決您的問題,本地變量都不見了完成處理程序被調用之前。 [handler copy]負責處理該塊中引用的局部變量,以便即使在程序流退出了創建塊的方法之後,局部變量也不會消失。

記住下面的事實:

  1. 塊實例捕獲塊中提到的局部變量。
  2. 但是,塊實例在堆棧上。當程序流程超出了您創建塊的範圍{...}時,即使您保留它,它也將消失。
  3. 所以,你需要copy它,而不僅僅是retain它,如果你想使用後來的數據,就像你在這裏做的那樣。 Copy自動加入retain s從塊中引用的所有局部對象變量。
  4. 一旦你完成它,你需要release。它釋放塊本身的內存,並將release消息發送到所引用的本地對象變量。但是,如果您使用GC,則不必關心這一點。

要了解該塊的更多細節,我發現文章here邁阿密灰非常有幫助。

+0

嗨Yuji,感謝您的信息!這解決了這個問題。 – 2010-01-26 22:11:21