當(dāng)需要實現(xiàn)類似“輪詢”這種操作的時候,我們可能會希望有一個“被放緩了的” for 循環(huán) —— 即當(dāng)某次操作執(zhí)行后哈街,稍等一下再去執(zhí)行下一次操作。這時有幾種方法可以供我們使用,來實現(xiàn)這種效果坷虑,下面對比總結(jié)一下。
perform(_ aSelector: Selector, with anArgument: Any?, afterDelay delay: TimeInterval)
extension NSObject {
open func perform(_ aSelector: Selector, with anArgument: Any?, afterDelay delay: TimeInterval, inModes modes: [RunLoopMode])
open func perform(_ aSelector: Selector, with anArgument: Any?, afterDelay delay: TimeInterval)
open class func cancelPreviousPerformRequests(withTarget aTarget: Any, selector aSelector: Selector, object anArgument: Any?)
open class func cancelPreviousPerformRequests(withTarget aTarget: Any)
}
extension RunLoop {
open func perform(_ aSelector: Selector, target: Any, argument arg: Any?, order: Int, modes: [RunLoopMode])
open func cancelPerform(_ aSelector: Selector, target: Any, argument arg: Any?)
open func cancelPerformSelectors(withTarget target: Any)
}
這是系統(tǒng)提供的 API埂奈,其中最簡單的第 2 個方法可以通過指定方法迄损、參數(shù)、延遲時間來實現(xiàn)延遲調(diào)用账磺。
優(yōu)點:使用簡單芹敌、自帶根據(jù) target 取消調(diào)用的機(jī)制 并且可以指定對象、方法來取消延遲調(diào)用 使得這個方法可以完成一些復(fù)雜的延遲調(diào)用機(jī)制
缺點:系統(tǒng)幫你自動完成了很多操作垮抗,使得它不像定時器(NSTimer)那樣高度可控党窜。
scheduledTimer(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool) -> Timer
open class Timer : NSObject {
public /*not inherited*/ init(timeInterval ti: TimeInterval, invocation: NSInvocation, repeats yesOrNo: Bool)
open class func scheduledTimer(timeInterval ti: TimeInterval, invocation: NSInvocation, repeats yesOrNo: Bool) -> Timer
public /*not inherited*/ init(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool)
open class func scheduledTimer(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool) -> Timer
}
通過常見的定時器也可以實現(xiàn)延遲調(diào)用,把 repeats 參數(shù)置為 false借宵,可以實現(xiàn)類似上面的 perform 的效果。
優(yōu)點:定時器狀態(tài)可控矾削,可以重新賦值壤玫,可以查看是否 valid 等
缺點:對比上面的 perform 方法可以直接傳參,這里想要傳參的話只能曲線救國:
- 把參數(shù)放在 timer 的 userInfo 里面哼凯,再把 timer 本身當(dāng)成參數(shù)傳遞(這里使得代碼可讀性稍稍變差欲间,但是好在 userInfo 里面什么都能放,這使得我們可以同時傳遞多個參數(shù)了)
- 如果你的代碼可以不兼容 iOS 10 以下的系統(tǒng)断部,新的 API 可以讓你不通過 selector 而是通過 block (closure) 執(zhí)行代碼
asyncAfter(deadline: DispatchTime, qos: DispatchQoS = default, flags: DispatchWorkItemFlags = default, execute work: @escaping @convention(block) () -> Swift.Void)
DispatchQueue.main.asyncAfter(wallDeadline: DispatchWallTime.now() + 1, execute: {
print("1 second after")
})
上面這段代碼猎贴,可以在 1 秒之后,通過主線程執(zhí)行 print。值得注意的是她渴,設(shè)定時間的時候达址,有兩種類型,一種是 DispatchTime趁耗,這個時間本質(zhì)上是相對時間沉唠,它會在系統(tǒng)休眠的時候暫停,另外一種是 DispatchWallTime苛败,這個時間正如其名满葛,是“墻上的掛鐘時間”,是絕對時間罢屈,比如你可能希望某一個任務(wù)準(zhǔn)確地在x小時嘀韧、x分鐘、x秒之后執(zhí)行缠捌,這段時間可能發(fā)生任何事情锄贷,這時推薦使用 DispatchWallTime.
神奇而偉大的 GCD 這里就不多做介紹了,有太多文章講解它了
優(yōu)點:執(zhí)行的是閉包鄙币,可以隨意傳參
缺點:一旦開啟肃叶,無法取消,只能提前在閉包里面添加嚴(yán)謹(jǐn)?shù)倪壿嬇袛嗔?/p>