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

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

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


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

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

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

我试过了:

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

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


当前回答

正如许多人所说,选择器是一种动态调用方法的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的旧名字

其他回答

使用#selector将在编译时检查代码,以确保要调用的方法确实存在。更好的是,如果方法不存在,你会得到一个编译错误:Xcode将拒绝构建你的应用,从而消除另一个可能的错误来源。

override func viewDidLoad() {
        super.viewDidLoad()

        navigationItem.rightBarButtonItem =
            UIBarButtonItem(barButtonSystemItem: .Add, target: self,
                            action: #selector(addNewFireflyRefernce))
    }

    func addNewFireflyReference() {
        gratuitousReferences.append("Curse your sudden but inevitable betrayal!")
    }

斯威夫特4.1 与样本的轻拍手势

let gestureRecognizer = UITapGestureRecognizer()
self.view.addGestureRecognizer(gestureRecognizer)
gestureRecognizer.addTarget(self, action: #selector(self.dismiss(completion:)))

// Use destination 'Class Name' directly, if you selector (function) is not in same class.
//gestureRecognizer.addTarget(self, action: #selector(DestinationClass.dismiss(completion:)))


@objc func dismiss(completion: (() -> Void)?) {
      self.dismiss(animated: true, completion: completion)
}

有关选择器表达式的更多细节,请参阅Apple的文档

自从Swift 3.0发布以来,它甚至更微妙地声明了一个targetAction合适

class MyCustomView : UIView {

    func addTapGestureRecognizer() {

        // the "_" is important
        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(MyCustomView.handleTapGesture(_:)))
        tapGestureRecognizer.numberOfTapsRequired = 1
        addGestureRecognizer(tapGestureRecognizer)
    }

    // since Swift 3.0 this "_" in the method implementation is very important to 
    // let the selector understand the targetAction
    func handleTapGesture(_ tapGesture : UITapGestureRecognizer) {

        if tapGesture.state == .ended {
            print("TapGesture detected")
        }
    }
}

创建如下所示的选择器。 1.

UIBarButtonItem(
    title: "Some Title",
    style: UIBarButtonItemStyle.Done,
    target: self,
    action: "flatButtonPressed"
)

2.

flatButton.addTarget(self, action: "flatButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside)

注意,@selector语法消失了,取而代之的是一个简单的String来命名要调用的方法。有一个方面,我们都同意冗长是一个障碍。当然,如果我们声明有一个名为flatButtonPressed的目标方法:我们最好写一个:

func flatButtonPressed(sender: AnyObject) {
  NSLog("flatButtonPressed")
}

设置定时器:

    var timer = NSTimer.scheduledTimerWithTimeInterval(1.0, 
                    target: self, 
                    selector: Selector("flatButtonPressed"), 
                    userInfo: userInfo, 
                    repeats: true)
    let mainLoop = NSRunLoop.mainRunLoop()  //1
    mainLoop.addTimer(timer, forMode: NSDefaultRunLoopMode) //2 this two line is optinal

为了完整,这里是flatButtonPressed

func flatButtonPressed(timer: NSTimer) {
}

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

例如,我发现当设置一个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")
}