为什么performSelector不存在于swift中

时间:2014-12-21 20:08:14

标签: ios swift

显然以下内容在swift中不再可用:

[self performSelector:@selector(onFlip) withObject:nil afterDelay:0.3];

如果仍然存在以下情况,为什么会这样:

NSObject.cancelPreviousPerformRequestsWithTarget(self, selector: singleTapSelector, object: nil)

不能使用performSelector吗?nsobject.cancel?为什么有取消功能而不是执行功能?

5 个答案:

答案 0 :(得分:16)

使用

NSTimer.scheduledTimerWithTimeInterval(delay, target: self, selector: "onFlip", userInfo: nil, repeats: false)

代替。不知道为什么另一个不可用。

答案 1 :(得分:11)

我们可以在Swift 1.x中轻松解锁这些方法!耶!

来自 perfromSelector 系列的这些方法实际上存在于Swift中,但它们在Swift 2.0之前被人为地隐藏(我认为是设计)。它们可以在Swift中使用调配和一些Objective-C运行时攻击来揭开。

只需添加此扩展程序文件NSObject+PerformSelector.swift,并使用符号为所有来电添加前缀。

在您的情况下代码:

[self performSelector:@selector(onFlip) withObject:nil afterDelay:0.3];

可以像这样在Swift中重写:

self.performSelector("onFlip", withObject: nil, afterDelay: 0.3)

使用这个神奇的类别(类扩展): 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)
    }

}

答案 2 :(得分:5)

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为要执行的动作添加延迟时间

答案 3 :(得分:3)

将Thomas Kilian的答案更进一步,主要是为了提高调用客户端的可读性,我已经定义了一个swift实用程序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

答案 4 :(得分:0)

在Swift 4中 使用它来处理这些类型的警告!

执行(#selector(yourMethodName),其中:nil,afterDelay:0,inModes:[])