我试图在Swift中创建一个NSTimer,但我遇到了一些麻烦。

NSTimer(timeInterval: 1, target: self, selector: test(), userInfo: nil, repeats: true)

Test()是同一个类中的一个函数。


我在编辑器中得到一个错误:

无法找到一个超载的'init'接受提供的 参数

当我把selector: test()改为selector: nil时,错误就消失了。

我试过了:

选择器:测试() 选择器:测试 选择器:选择器(测试())

但是什么都没用,我在参考文献中找不到解决方案。


当前回答

注意在哪里设置触发动作的控件可能会很有用。

例如,我发现当设置一个UIBarButtonItem时,我必须在viewDidLoad内创建按钮,否则我会得到一个无法识别的选择器异常。

override func viewDidLoad() {
    super.viewDidLoad() 

    // add button
    let addButton = UIBarButtonItem(image: UIImage(named: "746-plus-circle.png"), style: UIBarButtonItemStyle.Plain, target: self, action: Selector("addAction:"))
    self.navigationItem.rightBarButtonItem = addButton
}

func addAction(send: AnyObject?) {     
    NSLog("addAction")
}

其他回答

下面是一个关于如何在Swift上使用Selector类的快速示例:

override func viewDidLoad() {
    super.viewDidLoad()

    var rightButton = UIBarButtonItem(title: "Title", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("method"))
    self.navigationItem.rightBarButtonItem = rightButton
}

func method() {
    // Something cool here   
}

请注意,如果作为字符串传递的方法不起作用,它将在运行时失败,而不是在编译时失败,并使应用程序崩溃

同样,如果你的(Swift)类不是来自Objective-C类,那么你必须在目标方法名称字符串的末尾有一个冒号,你必须使用@objc属性与你的目标方法,例如。

var rightButton = UIBarButtonItem(title: "Title", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("method"))

@objc func method() {
    // Something cool here   
} 

否则你会在运行时得到一个“unrecognized Selector”错误。

只是为了以防别人有同样的问题,我与NSTimer没有其他答案固定的问题,是真正重要的提到,如果你正在使用一个类,不继承从NSObject直接或深层的层次结构(例如。手动创建的swift文件),其他答案都不会工作,即使指定如下:

let timer = NSTimer(timeInterval: 1, target: self, selector: "test", 
                    userInfo: nil, repeats: false)
func test () {}

除了从NSObject继承类之外,没有改变任何其他东西,我停止了“Unrecognized selector”错误,并让我的逻辑按预期工作。

当使用performSelector()时

/addtarget()/NStimer.scheduledTimerWithInterval()方法你的方法(匹配选择器)应该被标记为

@objc
For Swift 2.0:
    {  
        //...
        self.performSelector(“performMethod”, withObject: nil , afterDelay: 0.5)
        //...


    //...
    btnHome.addTarget(self, action: “buttonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
    //...

    //...
     NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector : “timerMethod”, userInfo: nil, repeats: false)
    //...

}

@objc private func performMethod() {
…
}
@objc private func buttonPressed(sender:UIButton){
….
}
@objc private func timerMethod () {
….
}

对于Swift 2.2, 你需要写“#selector()”而不是字符串和选择器名称,这样拼写错误和崩溃的可能性就不会再存在了。下面是示例

self.performSelector(#selector(MyClass.performMethod), withObject: nil , afterDelay: 0.5)

正如许多人所说,选择器是一种动态调用方法的objective - c方式,已经被带到了Swift中,在某些情况下我们仍然坚持使用它,比如UIKit,可能是因为他们在SwiftUI上工作来取代它,但一些api有更Swift的版本,比如Swift Timer,例如你可以使用

class func scheduledTimer(withTimeInterval interval: TimeInterval, 
                                            repeats: Bool, 
                                              block: @escaping (Timer) -> Void) -> Timer

相反,你可以这样称呼它

Timer.scheduledTimer(withTimeInterval: 1, 
                              repeats: true ) {
    ... your test code here
}

or

Timer.scheduledTimer(withTimeInterval: 1, 
                              repeats: true,
                              block: test)

方法test需要一个Timer参数,或者如果你想test需要一个命名参数

Timer.scheduledTimer(withTimeInterval: 1, 
                              repeats: true,
                              block: test(timer:))

你也应该使用Timer而不是NSTimer因为NSTimer是objective-c的旧名字