Swift中的“打开文件”对话框崩溃

Swift中的“打开文件”对话框崩溃,swift,xcode,nsfilemanager,nsopenpanel,Swift,Xcode,Nsfilemanager,Nsopenpanel,我想使用NSFilemanager中的“打开文件”对话框,但我的代码有时崩溃,有时正常工作,我不知道为什么。有时它工作100%,有时窗口是空的,有时对话框后面的背景显示在窗口中。当火山灰发生时,“信号:SIGABRT”显示在Xcode中 func openfiledlg (title: String, message: String) -> String { var myFiledialog: NSOpenPanel = NSOpenPanel() myFiledialo

我想使用NSFilemanager中的“打开文件”对话框,但我的代码有时崩溃,有时正常工作,我不知道为什么。有时它工作100%,有时窗口是空的,有时对话框后面的背景显示在窗口中。当火山灰发生时,“信号:SIGABRT”显示在Xcode中

func openfiledlg (title: String, message: String) -> String
{
    var myFiledialog: NSOpenPanel = NSOpenPanel()

    myFiledialog.prompt = "Öffnen"
    myFiledialog.worksWhenModal = true
    myFiledialog.allowsMultipleSelection = false
    myFiledialog.canChooseDirectories = false
    myFiledialog.resolvesAliases = true
    myFiledialog.title = title
    myFiledialog.message = message
    myFiledialog.runModal()
    var chosenfile = myFiledialog.URL
    if (chosenfile != nil)
    {
        var TheFile = chosenfile.absoluteString!
        return (TheFile)
    }
    else
    {
        return ("")
    }
}
我做错了什么?为什么会崩溃

应用程序未在主线程上运行。我总是打开一个新线程来运行我的程序。主线程只处理SpriteKit的屏幕更新,我在程序中使用SpriteKit

我刚刚建立了一个新的基于Cocoa的应用程序,让这个函数在主线程中运行,然后它就可以工作了。当我在Cocoa应用程序中启动线程时,它会崩溃,就像在SpriteKit环境中一样

我需要在Sprite工具包环境中启动一个新线程,因为如果我直接从AppDelegate启动主程序,更新将无法完成。主程序一直运行到整个SpriteKit退出,所以我没有机会在主线程中执行我的工作

崩溃发生在带有runModal()的行中,然后在“NSSavePanel.\u spAuxiliaryStorage”中:


你知道如何在不在主线程内执行的情况下解决此问题吗?

大多数用户界面(UI)调用都不是线程保存,这意味着它们只能在主线程中正常工作,不会出现崩溃和异常行为


这也是NSOpenPanel调用的问题。从主线程调用时,一切正常。

大多数用户界面(UI)调用都不是线程保存,这意味着它们只能在主线程中正常工作,不会出现崩溃和异常行为


这也是NSOpenPanel调用的问题。从主线程调用时,一切正常。

当您使用以下代码异步执行主线程中的命令块时,可以解决用户界面(UI)调用的限制(非线程保存):

dispatch_async(dispatch_get_main_queue())
{
    // This commands are executed ansychronously
}
因此,您必须为每个内置函数编写自己的函数,而不是像这样进行线程保存(例如打开文件对话框):

请注意,该块是异步调用的,这意味着您必须检查该块是否已被处理,是否已完成。因此,我添加了一个布尔变量“finsihed”,它显示,当块到达其末端时。如果没有此选项,则不会得到路径名,而只会得到一个空字符串


如果你感兴趣,我也会发布我的savefiledialog函数。如果是,请留下评论。

当您使用以下代码异步执行主线程中的命令块时,可以解决用户界面(UI)调用的限制(非线程保存):

dispatch_async(dispatch_get_main_queue())
{
    // This commands are executed ansychronously
}
因此,您必须为每个内置函数编写自己的函数,而不是像这样进行线程保存(例如打开文件对话框):

请注意,该块是异步调用的,这意味着您必须检查该块是否已被处理,是否已完成。因此,我添加了一个布尔变量“finsihed”,它显示,当块到达其末端时。如果没有此选项,则不会得到路径名,而只会得到一个空字符串


如果你感兴趣,我也会发布我的savefiledialog函数。如果是,请留下评论。

它在哪一行崩溃?你能加一个stacktrace吗?你确定要在主线程上调用它吗?你的应用程序是否有沙盒和/或签名?它在哪一行崩溃?你能加一个stacktrace吗?你确定要在主线程上调用它吗?你的应用程序是否有沙盒和/或签名?什么是“frac”?目前,Swift 1.2无法解析该标识符。frac给出了实数的小数部分。这是“var-Int(var)”。我目前使用Xcode 6.3.1,它编译wll。你必须进口可可,也许这是你的问题。Frac是标准数学的一部分,这个函数已经很久没有改变了。什么是“Frac”?目前,Swift 1.2无法解析该标识符。frac给出了实数的小数部分。这是“var-Int(var)”。我目前使用Xcode 6.3.1,它编译wll。你必须进口可可,也许这是你的问题。Frac是标准数学的一部分,该函数很久没有更改。
dispatch_async(dispatch_get_main_queue())
{
    // This commands are executed ansychronously
}
func not (b: Bool) -> Bool
{
    return (!b)
}

func suspendprocess (t: Double)
{
    var secs: Int = Int(abs(t))
    var nanosecs: Int = Int(frac(abs(t)) * 1000000000)
    var time = timespec(tv_sec: secs, tv_nsec: nanosecs)
    let result = nanosleep(&time, nil)
}

func openfiledialog (windowTitle: String, message: String, filetypelist: String) -> String
{
    var path: String = ""
    var finished: Bool = false

    suspendprocess (0.02) // Wait 20 ms., enough time to do screen updates regarding to the background job, which calls this function
    dispatch_async(dispatch_get_main_queue())
    {
        var myFiledialog: NSOpenPanel = NSOpenPanel()
        var fileTypeArray: [String] = filetypelist.componentsSeparatedByString(",")

        myFiledialog.prompt = "Open"
        myFiledialog.worksWhenModal = true
        myFiledialog.allowsMultipleSelection = false
        myFiledialog.canChooseDirectories = false
        myFiledialog.resolvesAliases = true
        myFiledialog.title = windowTitle
        myFiledialog.message = message
        myFiledialog.allowedFileTypes = fileTypeArray

        let void = myFiledialog.runModal()

        var chosenfile = myFiledialog.URL // Pathname of the file

        if (chosenfile != nil)
        {
            path = chosenfile!.absoluteString!
        }
        finished = true
    }

    while not(finished)
    {
        suspendprocess (0.001) // Wait 1 ms., loop until main thread finished
    }

    return (path)
}