@Swift中的选择器()?

@Swift中的选择器()?,swift,selector,nstimer,Swift,Selector,Nstimer,我正在尝试在Swift中创建NSTimer,但遇到了一些问题 NSTimer(timeInterval: 1, target: self, selector: test(), userInfo: nil, repeats: true) test()是同一类中的函数 我在编辑器中遇到一个错误: 找不到接受所提供内容的“init”的重载 论据 当我将selector:test()更改为selector:nil时,错误消失 我试过: 选择器:test() 选择器:测试 选择器:选择器(test(

我正在尝试在
Swift
中创建
NSTimer
,但遇到了一些问题

NSTimer(timeInterval: 1, target: self, selector: test(), userInfo: nil, repeats: true)
test()
是同一类中的函数


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

找不到接受所提供内容的“init”的重载 论据

当我将
selector:test()
更改为
selector:nil
时,错误消失

我试过:

  • 选择器:test()
  • 选择器:测试
  • 选择器:选择器(test())
但是什么都不起作用,我在参考资料中也找不到解决方案。

Swift本身不使用选择器-在Objective-C中使用选择器的几种设计模式在Swift中的工作方式不同。(例如,在协议类型或
is
/
as
测试中使用可选链接,而不是
响应选择器:
,并尽可能使用闭包,而不是
性能选择器:
,以提高类型/内存安全性。)

但是仍然有许多重要的基于ObjC的api使用选择器,包括计时器和目标/动作模式。Swift提供了
选择器
类型,用于处理这些文件。(Swift会自动使用此选项代替ObjC的
SEL
类型。)

在Swift 2.2(代码7.3)和更高版本(包括Swift 3/Xcode 8和Swift 4/Xcode 9)中: 您可以使用
#Selector
表达式从Swift函数类型构造
选择器

let timer = Timer(timeInterval: 1, target: object,
                  selector: #selector(MyClass.test),
                  userInfo: nil, repeats: false)
button.addTarget(object, action: #selector(MyClass.buttonTapped),
                 for: .touchUpInside)
view.perform(#selector(UIView.insertSubview(_:aboveSubview:)),
             with: button, with: otherButton)
这种方法的好处是什么?函数引用由Swift编译器检查,因此您只能将
#selector
表达式与实际存在且有资格用作选择器的类/方法对一起使用(请参见下面的“选择器可用性”)。您还可以根据需要自由地使函数引用尽可能具体

(这实际上是对ObjC的
@selector()
指令的改进,因为编译器的
-Wundeclared selector
检查只验证指定的选择器是否存在。传递给
#selector
的Swift函数引用检查存在性、类中的成员资格和类型签名。)

对于传递给
#selector
表达式的函数引用,有几个额外的注意事项:

  • 通过使用上述参数标签(例如
    insertSubview(\uu:at:)
    vs
    insertSubview(\uu:oversubview:)
    ),可以区分具有相同基本名称的多个函数。但是,如果函数没有参数,消除歧义的唯一方法是使用带有函数类型签名的
    as
    强制转换(例如
    fooas()->()
    vs
    foo(:)
  • Swift 3.0+中的属性getter/setter对有一种特殊的语法。例如,给定一个
    var foo:Int
    ,您可以使用
    选择器(getter:MyClass.foo)
    选择器(setter:MyClass.foo)
一般说明:
#选择器
不起作用的情况下,命名:
有时您没有用于创建选择器的函数引用(例如,使用在ObjC运行时动态注册的方法)。在这种情况下,您可以从字符串构造一个
选择器
:例如
选择器(“dynamicMethod:”)
——尽管您会丢失编译器的有效性检查。执行此操作时,需要遵循ObjC命名规则,包括每个参数的冒号(

选择器可用性:选择器引用的方法必须公开给ObjC运行时。在Swift 4中,暴露于ObjC的每个方法的声明必须以
@ObjC
属性开头。(在以前的版本中,在某些情况下可以免费获得该属性,但现在必须显式声明它。)

请记住,
private
符号也不会暴露于运行时-您的方法至少需要具有
内部
可见性

关键路径:这些路径与选择器相关,但并不完全相同。swift3中也有一种特殊的语法:例如,
chris.valueForKeyPath(#keyPath(Person.friends.firstName))
。有关详细信息,请参阅。更重要的是,如果合适的话,请确保您使用的是正确的基于键路径的API,而不是选择器

您可以在“将Swift与Cocoa和Objective-C结合使用”下阅读有关选择器的更多信息


注意:在Swift 2.2之前,
Selector
符合
StringLiteralConvertible
,因此您可能会发现旧代码将裸字符串传递给使用选择器的API。您需要在Xcode中运行“Convert to Current Swift Syntax”(转换为当前Swift语法),以获取使用
#selector
的语法。下面是一个关于如何在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   
}

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

选择器是Objective-C中方法名称的内部表示形式。在Objective-C中,“@selector(methodName)”会将源代码方法转换为SEL的数据类型。由于不能在Swift中使用@selector语法(rickster在这一点上),因此必须手动将方法名称直接指定为String对象,或者将String对象传递给选择器类型。以下是一个例子:

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

此外,如果您的(Swift)类不是从Objective-C类派生的,那么您必须在目标方法名称字符串的末尾有一个冒号,并且您必须对目标方法使用@objc属性,例如

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

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

否则,您将在运行时遇到“无法识别的选择器”错误。

您将创建如下选择器。
一,

2.

flatButton.addTarget(self, action: "flatButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
请注意,@selector语法已经消失,取而代之的是命名要调用的方法的简单字符串。有一个方面,我们都可以同意,冗长的语言妨碍了我们。当然,如果我们声明有一个名为fl的目标方法
UIBarButtonItem(
    title: "Some Title",
    style: UIBarButtonItemStyle.Done,
    target: self,
    action: "flatButtonPressed"
)
flatButton.addTarget(self, action: "flatButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
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
func flatButtonPressed(timer: NSTimer) {
}
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")
}
let timer = NSTimer(timeInterval: 1, target: self, selector: "test", 
                    userInfo: nil, repeats: false)
func test () {}
Create Refresh control using Selector method.   
    var refreshCntrl : UIRefreshControl!
    refreshCntrl = UIRefreshControl()
    refreshCntrl.tintColor = UIColor.whiteColor()
    refreshCntrl.attributedTitle = NSAttributedString(string: "Please Wait...")
    refreshCntrl.addTarget(self, action:"refreshControlValueChanged", forControlEvents: UIControlEvents.ValueChanged)
    atableView.addSubview(refreshCntrl)
func refreshControlValueChanged(){
    atableView.reloadData()
    refreshCntrl.endRefreshing()

}
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)
}
var timer1 : NSTimer? = nil
timer1= NSTimer(timeInterval: 0.1, target: self, selector: Selector("test"), userInfo: nil, repeats: true)
button.addTarget(self, action: #selector(clickedButton(sender:)), for: UIControlEvents.touchUpInside)
@objc func clickedButton(sender: AnyObject) {

}
let tapRecognizer = UITapGestureRecognizer(
            target: self,
            action: "labelTapped:")
func labelTapped(sender: UILabel) { }
let tapRecognizer = UITapGestureRecognizer(
            target: self,
            action: Selector("labelTapped:"))
@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 () {
….
}
self.performSelector(#selector(MyClass.performMethod), withObject: nil , afterDelay: 0.5)
Selector("keyboardDidHide:")
#selector(keyboardDidHide(_:))
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!")
    }
// for swift 2.2
// version 1
buttton.addTarget(self, action: #selector(ViewController.tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(ViewController.tappedButton2(_:)), forControlEvents: .TouchUpInside)

// version 2
buttton.addTarget(self, action: #selector(self.tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(self.tappedButton2(_:)), forControlEvents: .TouchUpInside)

// version 3
buttton.addTarget(self, action: #selector(tappedButton), forControlEvents: .TouchUpInside)
buttton.addTarget(self, action: #selector(tappedButton2(_:)), forControlEvents: .TouchUpInside)

func tappedButton() {
  print("tapped")
}

func tappedButton2(sender: UIButton) {
  print("tapped 2")
}

// swift 3.x
button.addTarget(self, action: #selector(tappedButton(_:)), for: .touchUpInside)

func tappedButton(_ sender: UIButton) {
  // tapped
}

button.addTarget(self, action: #selector(tappedButton(_:_:)), for: .touchUpInside)

func tappedButton(_ sender: UIButton, _ event: UIEvent) {
  // tapped
}
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")
        }
    }
}
let timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.test), userInfo: nil, repeats: true)
@objc func test()
{
    // my function
} 
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)
}
Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(updateTimer)), userInfo: nil, repeats: true)

WHERE
timeInterval:- Interval in which timer should fire like 1s, 10s, 100s etc. [Its value is in secs]
target:- function which pointed to class. So here I am pointing to current class.
selector:- function that will execute when timer fires.

func updateTimer(){
    //Implemetation 
} 

repeats:- true/false specifies that timer should call again n again.
button.addTarget(self, action: #selector(buttonTapped(sender:)), for: UIControlEvents.touchUpInside)
Selector("foo:")
unrecognized selector sent to instance
#selector(foo(_:))