我被困住了!
我正在尝试创建自定义模式对话框。我希望它使用块作为完成处理程序来执行与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:已经完成它不会阻塞线程,所以即使用户没有选择“ok”或“cancel”,也会打印“Errg”。此时显示模态窗口,用户单击“确定”,然后执行_handler块。但是,如果我尝试访问块中的局部变量,并且应用程序崩溃,因为所有内容已经清理过。
从makeKeyAndOrderFront:...方法阻止主线程的最佳方法是什么?这是使用块实现完成处理程序的正确方法吗?
答案 0 :(得分:5)
你的行
_handler=[handler retain];
应该是
_handler=[handler copy];
这应该可以解决您的问题,即在调用完成处理程序之前局部变量已经消失。
[handler copy]
负责处理块中引用的局部变量,这样即使程序流退出您创建块的方法,局部变量也不会消失。
请记住以下事实:
{...}
时,即使您保留它也会消失。copy
它,而不仅仅是retain
,如果您想在之后使用数据,就像在这里一样。 Copy
自动retain
从块中引用的所有本地对象变量。release
。它为块本身释放内存,并将release
消息发送到所引用的本地对象变量。如果你使用GC,你不必关心它。要了解该块的更多细节,我发现Mike Ash的文章here非常有用。