无法在Swift中使我的计时器在Playground

时间:2015-10-27 22:14:45

标签: swift swift2 grand-central-dispatch swift-playground

我正在尝试使用Swift和GCD制作一个漂亮的计时器。我在Matt Neuburg的书中找到了很多博客甚至是一篇文章。我使用后者将我自己的变体放在一个操场上:

import Foundation
struct Timer {
    private var queue = dispatch_queue_create("timer", nil)
    private var source: dispatch_source_t
    var tick:()->() = {} {
        didSet {
            self.update()
        }
    }
    var rate:Double = 1.0 {
        didSet {
            self.update()
        }
    }

    init() {
        self.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.queue)
        self.update()
    }

    func cancel() {
        dispatch_source_cancel(self.source)
    }

    func update() {
        dispatch_source_set_timer(self.source, DISPATCH_TIME_NOW, UInt64(Double(NSEC_PER_SEC) / self.rate), 0)
        dispatch_source_set_event_handler(self.source, self.tick)
    }

    func resume() {
        dispatch_resume(self.source)
    }
}

var timer = Timer()
timer.tick = {
    let now = NSDate()
    print("\(now)")
}
timer.cancel()
timer.resume()

我没有编译错误。但是操场底部的控制台什么都没显示。如果我添加

timer.tick()

它输出当前日期的结果,显然执行一次滴答功能。我非常密切地跟随马特在他的书中的例子(为教育目的做了一些小改动)。所以我不知道是否

A)它很好,当我将它移动到实际代码时工作正常,它只是在Playground输出中没有显示任何明显的 B)没有遗漏的事情并没有真正解雇

1 个答案:

答案 0 :(得分:2)

一旦dispatch_source_cancel取消了某个来源,它就永远不会再次调用其事件处理程序。取消后,您无法使用dispatch_resume重新启用来源;你必须创造一个新的来源。

要使您的游乐场有效,您必须取消对timer.cancel()的调用。

此外,在执行完整个游乐场脚本后,默认情况下会退出游乐场进程。如果您希望它继续运行,则需要设置XCPlaygroundPage.currentPage.needsIndefiniteExecution = true

因此,让脚本的结尾如下所示:

var timer = Timer()
timer.tick = {
    let now = NSDate()
    print("\(now)")
}
timer.resume()
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true