具有块完成处理程序的自定义模式窗口 [英] Custom Modal Window with Block Completion Handler

查看:19
本文介绍了具有块完成处理程序的自定义模式窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我被困住了!

我正在尝试创建自定义模式对话框.我希望它使用块作为完成处理程序来执行类似于 NSSavePanel 的操作.

I am trying to create a custom modal dialog. I would like it to perform similarly to the NSSavePanel using a block as a completion handler.

我只复制了我认为需要的重要片段.

I've copied only the important snippets I think are needed.

@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

现在我可以使用代码调用它了:

Now I can call this using the code:

[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 块.但是,如果我试图访问块中的局部变量,并且应用程序崩溃,因为一切都已经清理完毕.

All goes well however, after the method makeKeyAndOrderFront:modalToWindow:sourceRect:completionHandler: has completed it does not block the thread, so "Errg" will be printed even though the user has not selected "ok" or "cancel". The modal window is displayed at this point, where the user clicks OK and the _handler block is then executed. However if I am trying to access local variables in the block, and the app crashes as everything has cleaned up already.

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

What is the best approach to blocking the main thread from the makeKeyAndOrderFront:... method? Is this the right approach to implementing a completion handler using blocks?

推荐答案

你的行

_handler=[handler retain];

应该是

_handler=[handler copy];

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

That should solve your problem, that the local variables are gone before the completion handler is called. [handler copy] takes care of the local variables referred to in the block, so that the local variables don't go away even after the flow of the program exited the method where you made the block.

记住以下事实:

  1. 块实例捕获块内引用的局部变量.
  2. 但是,块实例在堆栈上.当程序的流程超出您创建块的范围 {...} 时,即使您保留它,它也会消失.
  3. 所以,如果您想在之后使用数据,您需要复制 它,而不仅仅是retain 它,就像您在此处所做的那样.复制自动保留从块中引用的所有局部对象变量.
  4. 你需要在完成后release它.它为块本身释放内存,并将 release 消息发送到引用的本地对象变量.不过,如果您使用 GC,则不必关心这一点.
  1. The block instance captures the local variables referred inside the block.
  2. However, the block instance is on the stack. It will go away even you retain it, when the flow of the program go out of the scope {...} in which you create the block.
  3. So, you need to copy it, not just retain it, if you want to use the data afterwards, as you are doing here. Copying it automatically retains all the local object variables referred to from the block.
  4. You need to release it once you're done with it. It deallocates the memory for the block itself, and sends release message to the local object variables referred to. If you use GC, you don't have to care about this, though.

为了了解更多的区块细节,我找到了文章这里 by Mike Ash 很有帮助.

To understand more details of the block, I found the article here by Mike Ash very helpful.

这篇关于具有块完成处理程序的自定义模式窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆