可取消的后台任务:NSOperation,GCD还是NSThread?

时间:2015-08-14 17:23:09

标签: ios iphone multithreading swift

我是Swift的新手,不知道如何做到以下几点。

当点击按钮时,我需要启动后台任务来执行某些操作,当再次点击相同的按钮时,我需要停止这项任务。

我不确定是使用NSOperation,GCD还是NSThread

有人可以给我一个简单的例子吗?

1 个答案:

答案 0 :(得分:2)

由于您希望轻松取消正在运行的任务,我建议您使用NSOperation。 GCD没有提供取消执行块的内置方法,使用NSThread通常是矫枉过正。

以下是最小的工作示例。它在视图控制器内创建一个按钮。点按它后,系统会创建一个新的NSBlockOperation并将其添加到NSOperationQueue。再次点击它时,队列中的所有操作都将被取消。

import Foundation
import UIKit

class ViewController: UIViewController {

    // Create the queue to run our operation
    let queue = NSOperationQueue()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Create the button
        let button = UIButton.buttonWithType(.System) as! UIButton
        button.setTranslatesAutoresizingMaskIntoConstraints(false)
        button.setTitle("Tap me!", forState: .Normal)
        button.addTarget(self, action: "buttonTapped",
            forControlEvents: .TouchUpInside)
        view.addSubview(button)

        // Layout the button
        let views: [NSObject: AnyObject] = ["button": button]
        view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(
            "H:|-[button]-|", options: nil, metrics: nil, views: views))
        view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(
            "V:|-20-[button(44)]", options: nil, metrics: nil, views: views))
    }

    func buttonTapped() {
        if queue.operationCount == 0 {
            // Create a new operation
            let operation = NSBlockOperation()
            operation.addExecutionBlock { [weak operation] in
                while operation?.cancelled == false {
                    // Do something interesting as long as
                    // the operation was not canceled
                    println("do stuff")
                    sleep(1)
                }
                println("stop doing stuff")
            }

            // Add the operation to the queue (this will also
            // start the operation)
            queue.addOperation(operation)
        } else {
            // Cancel all operations in the queue
            queue.cancelAllOperations()
            // An alternative could be to keep a reference
            // to the single operation and cancel that one
            // instead. The effect is the same in this simple
            // example.
        }
    }

}

当您在模拟器中运行上述代码段时,您将能够在控制台上观察输出。