6

到目前为止,我有这个代码

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我最终会在不同的地方..

4

2 回答 2

5

正如评论中所指出的,这段代码是支持旧 iOS 版本的尝试的残余,这些旧版本不仅不再相关,而且在使用 Swift 开发时甚至不能作为目标。

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

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

(基于版本的可用性检查的另一个好处:当操作系统版本变得足够老以至于您放弃支持时,在您的代码中找到您可以清理的所有站点要容易得多。您不必记住哪个版本是哪个方法/属性变得普遍。)


如果由于某些其他原因您需要形成一个Selectorfor UIScreen.scale... 在 Swift 2.2 中您不能使用该#selector表达式来执行此操作,因为scale它是一个属性,而不是一个方法。在 Swift 2.2 中,#selector接受一个函数/引用,并且无法获取对属性的底层 getter 或 setter 方法的引用。您仍然需要从字符串构造该选择器。要绕过警告,请将字符串文字临时存储:

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

或者做一些传递字符串但不直接将字符串文字传递给Selector初始化程序的其他舞蹈:

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

在 Swift 3 中会有一种特殊形式的#selectorfor 属性 getters/setters,但它还没有落地。

于 2016-05-11T18:39:42.963 回答
3

我的两分钱:

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

让我们看看4个案例:

一个)

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



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


func doIt() {
    print("touched2 ")

}

'doIt'的模棱两可的使用

二)

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 代码(在 iOS 库中)将按钮地址推送到
    堆栈上,因为编译器确实创建了一个堆栈框架。
于 2016-08-19T12:47:44.340 回答