如何使用 Swift 3 个选择器?

How to use the Swift 3 selectors?

到目前为止我已经有了这个代码

if UIScreen.instancesRespondToSelector(Selector("scale")) {
  UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.mainScreen().scale);
}else{...}

我没有写这段代码,所以我不确定它的用途,但看起来他们想验证 UIScreen.mainScreen() 实际上可以有变量 .scale(? ).

在查看 .scale 时,我觉得它自 iOS 4.0 以来就可用了。既然我们支持低至 iOS 7,这应该不是必需的,对吧?

总之,这不是当前的问题。 由于 Xcode 7.3 向 Swift 3 以及这些新的选择器实例化或诸如此类的东西,我现在收到了数百条警告。

Xcode 想让我改变这个:

Selector("scale")

进入

#selector(NSDecimalNumberBehaviors.scale)

到目前为止,我更改的所有其他选择器都是合乎逻辑的,例如“将 Selector("hello") 更改为 #selector(MyClass.hello),但是这个 NSDecimal.. 听起来有点过激。我可以信任 Xcode 选择正确的选择器吗? 我找不到 NSDecimalNumberBehaviors 连接到 UIScreen.scale 的任何地方。如果我输入 #selector(UIScreen.scale) 我得到一个错误..

我唯一确定的是,如果我 CMD+单击 scale 此处:NSDecimalNumberBehaviors.scale 和此处:UIScreen.mainScreen().scale 我最终会在不同的地方..

如评论中所述,此代码是支持旧 iOS 版本的尝试的残余,这些旧版本不仅不再相关,而且在 Swift 中开发时甚至无法作为目标.

只需直接调用 UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.mainScreen().scale)scale 属性 存在于您可以使用 Swift 定位的所有 iOS 版本中,因此无需检查一下。

事实上,通常使用选择器检查来测试 API 可用性并不是一个好主意。选择器可能存在于低于您的目标版本的版本上,但是具有不同行为的私有 API — 因此您的检查会成功,但您的代码将无法正常运行。这就是 @available and #available system 在 Swift 2 中引入的原因。

(基于版本的可用性检查的另一个好处:当 OS 版本太旧以至于您可以放弃支持时,在您的代码中找到您可以清理的所有站点会容易得多。您不必记住 method/property 在哪个版本中通用。)


如果出于某些其他原因您需要为UIScreen.scale形成一个Selector...您不能使用#selector在 Swift 2.2 中执行此操作的表达式,因为 scale 是 属性,而不是方法。在 Swift 2.2 中,#selector 采用 function/reference,并且无法获得对 [=59= 的基础 getter 或 setter 方法的引用].您仍然需要从字符串构造该选择器。要绕过警告,请将字符串文字存储在临时文件中:

let scale = "scale"
let selector = Selector(scale)

或者做一些其他传递字符串的舞蹈,但不直接将字符串 文字 传递给 Selector 初始值设定项:

let selector = Selector({"scale"}())

在Swift3会有a special form of #selector for property getters/setters,但是还没有落地

我的两分钱:

  • 1) swift 有一个新的选择器语法
  • 2) 编译器可以安全地检测基于以下方法的方法:
    • n。参数
    • 每个参数的类型
    • 结果类型(仅在纯swift中,所以我们现在忘记它)

让我们看4个案例:

A)

..
        closeBtn.addTarget(self, action: #selector(doIt), for: .touchUpInside)
    }



func doIt(_ sender: UIButton) {
    print("touched")
}


func doIt() {
    print("touched2 ")

}

'doIt'

的使用不明确

B)

closeBtn.addTarget(self, action: #selector(doIt), for: .touchUpInside)
}


//  func doIt(_ sender: UIButton) {
//      print("touched")
//  }


func doIt() {
    print("touched2 ")

}

它有效,因为编译器能够检测到唯一的方法 可以匹配签名

C)

closeBtn.addTarget(self, action: #selector(doIt(_:)), for: .touchUpInside)
}

func doIt(_ sender: UIButton) {
    print("touched")
}


func doIt() {
    print("touched2 ")
}

它有效,因为编译器能够检测到唯一的方法 可以匹配签名。

D)

closeBtn.addTarget(self, action: #selector(doIt), for: .touchUpInside)
}


func doIt(_ sender: UIButton) {
    print("touched")
}

/*
func doIt() {
    print("touched2 ")

}
*/

有效并且:

  • 编译器能够检测到唯一可以匹配
    的方法 签名
  • 在调试器中你也会得到正确的按钮引用,因为 UIButton CODE (in iOS libs) 按下
    上的按钮地址 栈,因为编译器确实创建了一个栈帧。