如何关闭NSOpenPanel或为什么它不会自动关闭?

时间:2012-11-13 05:10:46

标签: objective-c macos cocoa nsopenpanel

我很难理解如何关闭NSOpenPanel。 会自动关闭,但需要的时间比我想要的要长。

这是我的代码:

- (IBAction)startProcess:(id)sender
{

   NSString *path = [Document openVideoFile]; // open file

   // some other method calls here
}

// NSOpenPanel for file picking
+(NSString*) openVideoFile
{
   NSOpenPanel *openDialog = [NSOpenPanel openPanel];

   //set array of the file types

   NSArray *fileTypesArray = [[NSArray alloc] arrayWithObjects:@"mp4", nil];

   [openDialog setCanChooseFiles:YES];
   [openDialog setAllowedFileTypes:fileTypesArray];
   [openDialog setAllowsMultipleSelection:FALSE];

   if ([openDialog runModal] == NSFileHandlingPanelOKButton)
   {      
      NSArray *files = [openDialog URLs];

      return [[files objectAtIndex:0] path];   
   }
   else
   {
      return @"cancelled";
   }
   return nil; // shouldn't be reached
}

有趣的是,如果用户点击“取消”,面板立即关闭,但如果用户从列表中选择一个文件,面板将保持打开状态,直到程序到达startProcess方法的末尾。

如果有人知道如何立即关闭面板,用户在选择文件后单击“确定”按钮后,我将非常感谢您的帮助!

谢谢!

3 个答案:

答案 0 :(得分:3)

我的猜测是,在startProcess:返回后,系统实际上并没有启动删除打开面板的动画,直到运行循环的后期。因此,如果您的“some other method calls here”需要很长时间才能运行,那么动画开始前需要很长时间。

理想的解决方案是在后台队列上执行慢速“其他方法调用”,因为您应该尽量避免阻塞主线程。但是,这可能需要你制作各种线程安全的东西,这些东西目前都不是,这可能很难。

另一种方法就是推迟在运行循环中执行它们:

- (IBAction)startProcess:(id)sender {
    NSString *path = [Document openVideoFile]; // open file
    dispatch_async(dispatch_get_main_queue(), ^{
       // some other method calls here
    });
}

或者您可能需要将其延长一段时间:

- (IBAction)startProcess:(id)sender {
    NSString *path = [Document openVideoFile]; // open file
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC / 100), dispatch_get_main_queue(), ^(void){
        // some other method calls here
    });
}

答案 1 :(得分:1)

在后台线程上做慢工作的建议很好。

但要更快关闭面板,只需在从[openDialog close]返回之前调用-openVideoFile

答案 2 :(得分:0)

另一个解决方案是给runloop一些时间来处理事件,然后再继续使用例如[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]]; ...像

if ([openDialog runModal] == NSFileHandlingPanelOKButton)
{      
  [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];

  NSArray *files = [openDialog URLs];

  return [[files objectAtIndex:0] path];   
}