Swift:如何让后台线程等待用户输入?

时间:2016-07-05 18:58:36

标签: swift

我有一个后台线程需要一些用户输入。由于不建议从后台线程调用NSAlert窗口,我喜欢在主线程中执行此操作。但是,如何让后台线程等到NSAlert窗口关闭?

let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0)) {
    // some background task

    dispatch_async(dispatch_get_main_queue()) {
        // UI task asking for user input:
        let alert = NSAlert()
        alert.messageText = "Some text"
        alert.informativeText = "Some information"
        alert.addButtonWithTitle("Yes")
        alert.addButtonWithTitle("No")
        result = alert.runModal()
    }

    // some background task, treating user input (Yes/No)
}

2 个答案:

答案 0 :(得分:3)

runModal方法是同步的。如果您想等待它完成,而不是使用dispatch_async异步调度到主队列,您可以通过与dispatch_sync同步调度来轻松实现您的要求,例如:

let queue = dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0)
dispatch_async(queue) {
    // some background task

    var result: NSModalResponse!

    dispatch_sync(dispatch_get_main_queue()) {     // note, `dispatch_sync`
        // UI task asking for user input:
        let alert = NSAlert()
        ...
        result = alert.runModal()
    }

    // some background task, treating user input (Yes/No)
}

一个更微妙的问题在于同步性runModal。这将阻止主线程。这通常不是一个好主意。它可能会干扰您的应用可能需要主线程执行的其他任务(定时器,动画,使用主队列的网络操作等)。

因此,您可以考虑使用完成处理程序向后台队列调度其他后台处理,而不是同步runModal,而不是同步NSAlert,例如:< / p>

beginSheetModalForWindow

这可以达到你想要的效果(当模态被解除时触发额外的后台任务),但具有不阻塞主线程的优点。

答案 1 :(得分:-2)

您可以使用信号量。

dispatch_async(dispatch_get_global_queue(priority, 0)) {
    // some background task

    //Create a semaphore with count = 0
    let semaphore = dispatch_semaphore_create(0)

    dispatch_async(dispatch_get_main_queue()) {
        // UI task asking for user input:
        let alert = NSAlert()
        alert.messageText = "Some text"
        alert.informativeText = "Some information"
        alert.addButtonWithTitle("Yes")
        alert.addButtonWithTitle("No")
        result = alert.runModal()
        //Signal semaphore
        dispatch_semaphore_signal(semaphore)
    }

    //Wait for semaphore
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
    // some background task, treating user input (Yes/No)
}

你不应该在主线程中“等待” 。但背景线程是其他事情。