上一節我們利用手勢控制,每當輕點螢幕就到https://picsum.photos/720/1280 抓圖更新畫面,那何不設計一個定時抓圖的程式,省掉輕點螢幕的動作,讓程式每隔5秒自動抓圖更新,就像一個無止盡的相片播放器。
實現方式需要用到一個新物件「定時器 Timer」,這是 Foundation 裡的物件,此物件跟 URLSession 類似,都是由作業系統所控制,如果應用程式需要的話,必須跟作業系統登記,由作業系統統一分發。
登記使用定時器物件的方法如下:
let 定時器 = Timer.publish(every: 5.0, on: .main, in: .common).autoconnect()
Timer.publish() 是定時器物件類型的一個「類型方法」 "type method",就像上一課的 URLSession.shared 是個類型屬性 "type property",類型方法是整個類型適用的函式,publish() 這個函式會產出一個定時器的物件實例。
為什麼稱為 publish() 呢?publish 是發行、發布的意思,因為在這個地方,作業系統與App的溝通模式跟網路連線很類似,術語稱為發布-訂閱模式 "Publisher-Subscriber",圖解如下:
在範例中,let 定時器 = Timer.publish() 是發布者,而視圖修飾語 .onReceive(定時器)是訂閱者。
Timer.publish() 的三個參數:
every: 5.0 on: .main in: .common
只有第一個參數 every 我們需要了解,是設定「每隔多久」發布一次通知,範例中為5.0秒。另外兩個 on: .main, in: .common 牽涉到作業系統的運作原理,我們暫不討論,但也不可省略。
這樣就會取得一個定時器的實例,完成登記,就像拿到一個號碼牌,每隔5.0秒鐘,作業系統會發一個「通知」給我們,不過這樣還沒有真的啟用,必須在最後一步使用物件方法 autoconnect() 來啟用:
let 定時器 = Timer.publish(every: 5.0, on: .main, in: .common).autoconnect()
這樣的過程是不是跟 URLSession.shared.dataTask().resume() 很類似?沒有錯,因為 Timer 和URLSession 一樣,都是非同步(asynchronous)的行為模式,我們看過範例程式後會更了解。