swift - @selector() 在 Swift 中?

标签 swift selector nstimer

我正在尝试创建一个 NSTimerSwift但我遇到了一些麻烦。

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

我在编辑器中收到错误消息:

Could not find an overload for 'init' that accepts the supplied arguments



当我改变selector: test()selector: nil错误消失。

我试过了:
  • selector: test()
  • selector: test
  • selector: Selector(test())

  • 但是没有任何效果,我在引用文献中找不到解决方案。

    最佳答案

    Swift 本身不使用选择器——Objective-C 中使用选择器的几种设计模式在 Swift 中的工作方式不同。 (例如,在协议(protocol)类型上使用可选链或 is/as 测试而不是 respondsToSelector: ,并尽可能使用闭包而不是 performSelector: 以获得更好的类型/内存安全。)
    但是仍然有许多重要的基于 ObjC 的 API 使用选择器,包括计时器和目标/ Action 模式。 Swift 提供了 Selector用于处理这些的类型。 (Swift 自动使用它来代替 ObjC 的 SEL 类型。)
    在 Swift 2.2 (Xcode 7.3) 及更高版本(包括 Swift 3/Xcode 8 和 Swift 4/Xcode 9)中:
    您可以构建一个 Selector从 Swift 函数类型使用 #selector表达。

    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表达式仅用于实际存在且有资格用作选择器的类/方法对(请参阅下面的“选择器可用性”)。您还可以根据 the Swift 2.2+ rules for function-type naming 自由地根据需要指定函数引用。 .
    (这实际上是对 ObjC 的 @selector() 指令的改进,因为编译器的 -Wundeclared-selector 检查仅验证命名选择器是否存在。传递给 #selector 的 Swift 函数引用检查是否存在、类中的成员身份和类型签名。 )
    对于传递给 #selector 的函数引用,还有一些额外的警告。表达:
  • 可以使用前面提到的 syntax for function references 通过参数标签区分具有相同基本名称的多个函数。 (例如 insertSubview(_:at:)insertSubview(_:aboveSubview:) )。但是如果一个函数没有参数,唯一的消除歧义的方法是使用 as使用函数的类型签名进行转换(例如 foo as () -> ()foo(_:) )。
  • 在 Swift 3.0+ 中,属性 getter/setter 对有一种特殊的语法。例如,给定一个 var foo: Int ,您可以使用 #selector(getter: MyClass.foo)#selector(setter: MyClass.foo) .

  • 一般注意事项:
    #selector的情况不起作用,并命名:有时您没有函数引用来创建选择器(例如,使用在 ObjC 运行时中动态注册的方法)。在这种情况下,您可以构造一个 Selector来自字符串:例如Selector("dynamicMethod:") ——虽然你失去了编译器的有效性检查。这样做时,您需要遵循 ObjC 命名规则,包括每个参数的冒号 ( : )。
    选择器可用性:选择器引用的方法必须暴露给 ObjC 运行时。在 Swift 4 中,每个暴露给 ObjC 的方法都必须以 @objc 开头的声明。属性。 (在以前的版本中,您在某些情况下可以免费获得该属性,但现在您必须明确声明它。)
    请记住 private符号也不会暴露给运行时——你的方法至少需要有 internal能见度。
    关键路径:这些与选择器相关但并不完全相同。在 Swift 3 中也有一个特殊的语法:例如chris.valueForKeyPath(#keyPath(Person.friends.firstName)) .见 SE-0062详情。甚至更多 KeyPath stuff in Swift 4 ,因此请确保在适当的情况下使用正确的基于 KeyPath 的 API 而不是选择器。
    您可以在 Interacting with Objective-C APIs 下阅读有关选择器的更多信息在将 Swift 与 Cocoa 和 Objective-C 结合使用。
    注:在 Swift 2.2 之前,Selector符合 StringLiteralConvertible ,因此您可能会发现旧代码将裸字符串传递给采用选择器的 API。您需要在 Xcode 中运行“Convert to Current Swift Syntax”以获得使用 #selector 的那些。 .

    关于swift - @selector() 在 Swift 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24007650/

    相关文章:

    html - sIFR 3 - 选择器

    iphone - 应用程序在后台时计划的 NSTimer?

    ios - 适用于 iPod Touch 4G 的 iPhone 模拟器

    ios - 加载图像后调整 UITableViewCell 的大小

    ios - UIView 出现错误的中心位置

    ios - UIView 可以在初始化后加载另一个 Nib 吗?

    javascript - Jquery:在.append中传递ID

    ios - 更新 map skobbler 流程

    android - 如何在线性布局中按下特定 TextView 时更改文本颜色

    iphone - Int 值持久化