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

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

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


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

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

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

我试过了:

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

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


当前回答

使用#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!")
    }

其他回答

自从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")
        }
    }
}

Swift 2.2+和Swift 3更新

使用新的#selector表达式,它消除了使用字符串文字的需要,使使用更不容易出错。供参考:

Selector("keyboardDidHide:")

就变成了

#selector(keyboardDidHide(_:))

参见:快速进化提案

注意(Swift 4.0):

如果使用# selector,你需要将函数标记为@objc

例子:

@objc func something(_ sender: UIButton)

斯威夫特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的文档

选择器是Objective-C中方法名的内部表示。在Objective-C中,“@selector(methodName)”会将一个源代码方法转换为SEL的数据类型。因为你不能在Swift中使用@selector语法(里克斯特就在这里),你必须手动指定方法名直接作为String对象,或者通过传递String对象给Selector类型。这里有一个例子:

var rightBarButton = UIBarButtonItem(
    title: "Logout", 
    style: UIBarButtonItemStyle.Plain, 
    target: self, 
    action:"logout"
)

or

var rightBarButton = UIBarButtonItem(
    title: "Logout", 
    style: UIBarButtonItemStyle.Plain, 
    target: self, 
    action:Selector("logout")
)

如果你想从NSTimer中传递一个参数给函数,那么这里是你的解决方案:

var somethingToPass = "It worked"

let timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: "tester:", userInfo: somethingToPass, repeats: false)

func tester(timer: NSTimer)
{
    let theStringToPrint = timer.userInfo as String
    println(theStringToPrint)
}

在选择器文本(tester:)中包含冒号,参数则放在userInfo中。

你的函数应该以NSTimer作为参数。然后提取userInfo以获得传递的参数。