2015-10-27 26 views
1

我試圖用Swift和GCD製作一個不錯的計時器。我發現很多博客,甚至還有馬特紐伯格的書中的一個條目。我用後者把我自己的變體放在一個操場上:無法讓我的計時器在Swift中在操場上觸發

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)Somethings不會丟失,它是沒有真正開火

回答

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 
相關問題