objective-c - 带有 block 完成处理程序的自定义模式窗口

标签 objective-c cocoa modal-dialog objective-c-blocks

我卡住了!

我正在尝试创建自定义模式对话框。我希望它使用 block 作为完成处理程序来执行与 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: 完成后它不会阻塞线程,因此即使用户没有选择“确定”或“取消”也会打印“Errg”。此时会显示模态窗口,用户在此处单击“确定”,然后执行 _handler block 。但是,如果我尝试访问 block 中的局部变量,应用程序会崩溃,因为所有内容都已清理干净。

从 makeKeyAndOrderFront:... 方法阻塞主线程的最佳方法是什么?这是使用 block 实现完成处理程序的正确方法吗?

最佳答案

你的线路

_handler=[handler retain];

应该是

_handler=[handler copy];

这应该可以解决您的问题,即局部变量在调用完成处理程序之前就消失了。 [handler copy] 负责处理 block 中引用的局部变量,因此即使在程序流退出创建 block 的方法后,局部变量也不会消失。

记住以下事实:

  1. block 实例捕获 block 内引用的局部变量。
  2. 但是, block 实例在堆栈上。当程序流超出您创建 block 的范围 {...} 时,即使您保留它,它也会消失。
  3. 因此,您需要复制它,而不仅仅是保留它,如果您以后想使用这些数据,就像您在这里所做的那样。 复制自动保留 block 中引用的所有局部对象变量。
  4. 您需要在完成后发布它。它为 block 本身释放内存,并向引用的局部对象变量发送 release 消息。不过,如果您使用 GC,则不必关心这一点。

要了解该 block 的更多详细信息,我找到了文章 here Mike Ash 非常有帮助。

关于objective-c - 带有 block 完成处理程序的自定义模式窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2142259/

相关文章:

ios - mkannotation 中的自定义数据变量

iphone - 架构 armv7 的 undefined symbol : "_SCNetworkReachabilityCreateWithAddress"

javascript - 将键盘导航添加到幻灯片

cocoa - NSString 获取某些字符之间的文本

c++ - 在 C++ 中模态来自其他正在运行的线程的消息对话框

JQuery 工具模态叠加 - 在 IE8 中损坏

ios - 加速度计数据始终为负

ios - 在 UITableView 中禁用部分 Cell

objective-c - 拖动交换 NSView

objective-c - 为什么 Nib 加载会选取我的类别?