Ответ 1
Используйте
NSTimer.scheduledTimerWithTimeInterval(delay, target: self, selector: "onFlip", userInfo: nil, repeats: false)
вместо этого. Не знаю, почему другой недоступен.
очевидно, что следующее не доступно быстрее:
[self performSelector:@selector(onFlip) withObject:nil afterDelay:0.3];
почему это так, если все еще присутствует:
NSObject.cancelPreviousPerformRequestsWithTarget(self, selector: singleTapSelector, object: nil)
не работает nsobject.cancel с performSelector? почему есть функция отмены, но не выполняет функции?
Используйте
NSTimer.scheduledTimerWithTimeInterval(delay, target: self, selector: "onFlip", userInfo: nil, repeats: false)
вместо этого. Не знаю, почему другой недоступен.
Эти методы из семейства perfromSelector
фактически существуют в Swift, но они были искусственно скрыты (по дизайну, я думаю) до Swift 2.0. Они могут быть представлены с использованием swizzling и некоторых Objective-C хакеров в режиме Swift.
Просто добавьте этот файл расширения NSObject+PerformSelector.swift
и префикс всех вызовов с символом 🚀
.
В вашем случае код:
[self performSelector:@selector(onFlip) withObject:nil afterDelay:0.3];
можно переписать в Swift следующим образом:
self.🚀performSelector("onFlip", withObject: nil, afterDelay: 0.3)
Используя эту 🚀magical категорию (расширение класса):
NSObject+PerformSelector.swift
import Foundation
private var dispatchOnceToken: dispatch_once_t = 0
private var selectors: [Selector] = [
"performSelector:",
"performSelector:withObject:",
"performSelector:withObject:withObject:",
"performSelector:withObject:afterDelay:inModes:",
"performSelector:withObject:afterDelay:",
]
private func swizzle() {
dispatch_once(&dispatchOnceToken) {
for selector: Selector in selectors {
let 🚀selector = Selector("🚀\(selector)")
let method = class_getInstanceMethod(NSObject.self, selector)
class_replaceMethod(
NSObject.self,
🚀selector,
method_getImplementation(method),
method_getTypeEncoding(method)
)
}
}
}
extension NSObject {
func 🚀performSelector(selector: Selector) -> AnyObject? {
swizzle()
return self.🚀performSelector(selector)
}
func 🚀performSelector(selector: Selector, withObject object: AnyObject?) -> AnyObject? {
swizzle()
return self.🚀performSelector(selector, withObject: object)
}
func 🚀performSelector(selector: Selector, withObject object1: AnyObject?, withObject object2: AnyObject?) -> AnyObject? {
swizzle()
return self.🚀performSelector(selector, withObject: object1, withObject: object2)
}
func 🚀performSelector(selector: Selector, withObject object: AnyObject?, afterDelay delay: NSTimeInterval, inModes modes: [AnyObject?]?) {
swizzle()
self.🚀performSelector(selector, withObject: object, afterDelay: delay, inModes: modes)
}
func 🚀performSelector(selector: Selector, withObject object: AnyObject?, afterDelay delay: NSTimeInterval) {
swizzle()
self.🚀performSelector(selector, withObject: object, afterDelay: delay)
}
}
func performFlipOnDelay() {
let delayInSeconds = 1.0
let delay = dispatch_time(DISPATCH_TIME_NOW, Int64(delayInSeconds * Double(NSEC_PER_SEC)))
dispatch_after(delay, dispatch_get_main_queue()) {
onFlip();
}
}
Еще один раунд ответа будет выше, используя GCD, чтобы добавить время задержки для выполняемого действия.
Принимая ответ от Томаса Килиана еще на шаг, прежде всего для повышения удобочитаемости при вызове клиентов, я определил быструю утилиту TimerUtil.swift, определяющую фасад на NSTimer для этой конкретной утилиты:
import Foundation
/**
* Convenience function to make a single timer scheduling more readable.
*/
public func invoke( selector:Selector, on target:AnyObject, afterDelay delay:NSTimeInterval ) {
NSTimer.scheduledTimerWithTimeInterval( delay, target: target, selector: selector, userInfo: nil, repeats: false )
}
Затем ваш код может просто вызвать:
invoke( "onFlip", on:self, afterDelay:0.3 )
который более или менее похож на performSelector: withObject: afterDelay