Swift更新至2.2版本 语言变化

1.容许(大部分)关键字做为参数标签程序员

参数标签是swift函数的接口的一个重要组成部分,描述特定参数的函数,提升可读性。有时候,最天然的与语言关键字标签一个论点一致标签,例如,重复,或推迟。应该容许这样的关键词做为参数标签,容许更好的表达这些接口。swift

 

动机是什么?api

在一些功能,标签为特定参数的最佳理由正好和语言关键字。例如,考虑一个module-scope函数,发现集合中的一个特定值的指数。天然语言是这样indexOf(_:in:):闭包

indexOf(value, in: collection)

然而,由于在一个关键字,会须要使用引号的逃避,eg:
indexOf(value, `in`: collection)
在swift特定义新的api时,做者每每会选择其余non-keyword的话(如。within 例子中),即便他们并不理想.然而,这个问题也出如今导入objective - c api”省略没必要要的词“启发式,要求摆脱使用这些api.例如:
event.touchesMatching([.Began, .Moved], `in`: view) NSXPCInterface(`protocol`: SomeProtocolType.Protocol)


提出解决方案:容许使用的关键词除了inout、var,le t 参数标签。这会影响三个地方的语法:
1.调用表达式,好比上面的示例。在这里,咱们没有这样的含糊不清,由于“:”不出如今任何语法在括号表达式列表。到目前为止,这是最重要的。
2.函数/下标/初始值设定项声明:除了上面的三个除外,这里没有歧义,由于关键字永远是紧随其后的是一个标识符,“:”,或者“_”。例如:
func touchesMatching(phase: NSTouchPhase, in view: NSView?) -> Set<NSTouch>


介绍的关键字或修改一个参数——目前只是“inout”,“let”,“var”——将须要保留之前的含义。若是咱们发明一个API,使用这样的关键词,他们仍然须要back-ticked:
func addParameter(name: String, `inout`: Bool)
3.功能类型:# 2,这是很简单的,由于参数名称老是后跟一个“:”:
(NSTouchPhase, in: NSView?) -> Set<NSTouch> (String, inout: Bool) -> Void





2.元组比较运算符
== , != ,< , <= , > , >= 运算符进行比较
@warn_unused_result
public func == <A: Equatable, B: Equatable, C: Equatable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool { return lhs.0 == rhs.0 && lhs.1 == rhs.1 && lhs.2 == rhs.2 } @warn_unused_result public func != <A: Equatable, B: Equatable, C: Equatable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool { return lhs.0 != rhs.0 || lhs.1 != rhs.1 || lhs.2 != rhs.2 } @warn_unused_result public func < <A: Comparable, B: Comparable, C: Comparable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool { if lhs.0 != rhs.0 { return lhs.0 < rhs.0 } if lhs.1 != rhs.1 { return lhs.1 < rhs.1 } return lhs.2 < rhs.2 } @warn_unused_result public func <= <A: Comparable, B: Comparable, C: Comparable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool { if lhs.0 != rhs.0 { return lhs.0 < rhs.0 } if lhs.1 != rhs.1 { return lhs.1 < rhs.1 } return lhs.2 <= rhs.2 } @warn_unused_result public func > <A: Comparable, B: Comparable, C: Comparable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool { if lhs.0 != rhs.0 { return lhs.0 > rhs.0 } if lhs.1 != rhs.1 { return lhs.1 > rhs.1 } return lhs.2 > rhs.2 } @warn_unused_result public func >= <A: Comparable, B: Comparable, C: Comparable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool { if lhs.0 != rhs.0 { return lhs.0 > rhs.0 } if lhs.1 != rhs.1 { return lhs.1 > rhs.1 } return lhs.2 >= rhs.2 }





3. 用associatedtype 替换 typealias 关键字相关的类型声明、
介绍:
目前typealias关键字用于声明两种类型:
类型别名(替代名称为现有类型)
相关类型(占位符名称类型做为协议的一部分)
这两种声明是不一样的,应该使用不一样的关键字。这将强调它们之间的差别,减小周围的一些混乱的使用相关联的类型。拟议的新关键字是associatedtype。

动机是什么?
重用typealias相关类型声明是混乱在许多方面。它不明显,typealias协议意味着别的东西比在其余地方。初学者隐藏相关类型的存在,使他们误解了编写代码。目前还不清楚具体类型别名是禁止内部协议。特别是,2 + 3致使程序员编写

protocol Prot {
    typealias Container : SequenceType typealias Element = Container.Generator.Element }

没有意识到Element是一个新类型 用Container.Generator.Element的默认值去替换类型别名Container.Generator.Element。

然问 这样的代码
protocol Prot {
    typealias Container : SequenceType } extension Prot { typealias Element = Container.Generator.Element }

做为一个类型别名Container.Generator.Element声明Element。这些微妙的目前须要仔细考虑理解的语言。
解决方案 :
对于声明相关的类型,用associatedtype替换typealias关键字。这能够解决上面提到的问题:typealias如今能够只用于声明类型别名。初学者如今被迫学习相关类型在建立协议。如今能够显示一个错误消息,当有人试图建立一个类型别名在一个协议。这消除了困惑显示在前面的代码片断。
protocol Prot {
    associatedtype Container : SequenceType typealias Element = Container.Generator.Element // error: cannot declare type alias inside protocol, use protocol extension instead 不能声明类型别名内部协议, 使用协议扩展 }
 
protocol Prot {
    associatedtype Container : SequenceType } extension Prot { typealias Element = Container.Generator.Element }
选择关键词是:, , , , …typeassociatedrequiredtypeplaceholdertype
声明相关的类型,我建议添加associatedtype和轻视typealias在swift2.2中,和彻底删除typealias 在swift3。做为另外一个只是替换一个关键字,过渡到associatedtype能够轻易被自动化的风险没有任何破坏现有代码。




4.命名函数做为参数标签

介绍:
swift包括支持一级函数,这样任何函数(或方法)能够放在一个函数类型的值。然而,当指定一个函数的名称,咱们只能提供基本名称,(如insertSubview)没有标签的论证。对于重载函数,这意味着人们必须消除类型信息的基础上歧义,这是尴尬的和冗长的。这个提议容许一个提供参数标签当引用一个函数,消除了在大多数状况下须要提供类型的上下文。
Swift-evolution线程:这个提议是这里讨论的初稿。它包括支持命名getter / setter(分别由迈克尔·亨森在这里继续)。乔Groff让我相信,眼镜是一种更好的方法来处理getter / setter,因此我把他们从这个版本的建议。
动机是什么?
extension UIView { func insertSubview(view: UIView, at index: Int) func insertSubview(view: UIView, aboveSubview siblingSubview: UIView) func insertSubview(view: UIView, belowSubview siblingSubview: UIView) }

调用这些方法
someView.insertSubview(view, at: 3) someView.insertSubview(view, aboveSubview: otherView) someView.insertSubview(view, belowSubview: otherView)
let fn = someView.insertSubview // ambiguous: could be any of the three methods然而,当引用函数建立一个函数值,一个不能提供标签:
let fn: (UIView, Int) = someView.insertSubview // ok: uses insertSubview(_:at:)这个是模棱两可的:能够是任何的三个方法

可使用消除歧义的类型注解:

let fn: (UIView, UIView) = someView.insertSubview // error: still ambiguous! 仍然模棱两可

解决后者的状况下,一我的必须回到建立一个闭包:
let fn: (UIView, UIView) = { view, otherView in button.insertSubview(view, aboveSubview: otherView) }

这是痛苦的乏味。一个额外的动机:swift应该获得一些要求objective - c的方法选择器对于一个给定的方法(而不是写一个字符串)。这样的一个操做的参数可能会引用一个方法,将受益于任何方法可以名称,包括getter和setter。

解决方法:
我建议延长函数命名容许化合物swift名称(如。,insertSubview(_:aboveSubview:))可能发生的任何一个名字。具体地说,
let fn = someView.insertSubview(_:at:) let fn1 = someView.insertSubview(_:aboveSubview:)

具体来讲,相同的语法也能够指的是初始化,例如,
let buttonFactory = UIButton.init(type:)
“产生给定方法的objective - c选择器”操做将一个单独的建议的主题。然而,这是一种可能性,插图如何利用提出的语法:
let getter = Selector(NSDictionary.insertSubview(_:aboveSubview:)) // produces insertSubview:aboveSubview:.

无参数的函数引用仍须要经过上下文类型信息消歧
func foo(x: Int, y: Int = 7, strings: String...) { ... } let fn1 = foo(x:y:strings:) // okay let fn2 = foo(x:) // error: no function named 'foo(x:)'
当全部参数_,这提供了任何方法名称的能力
aGameView.insertSubview(_, aboveSubview: _)
或者
{ aGameView.insertSubview($0, aboveSubview: playingSurfaceView) }


5.引用oc 选择器的方法

#selector 关键字 引入oc 的方法
let sel = #selector(((UIView.insertSubview(_:at:)) as (UIView) -> (UIView, Int) -> Void))
as可用于中同名迅速消除歧义的方法


6.限制
AnySequence.init 任何序列
为了让AnySequence委托调用底层的序列,其初始化应该有额外的约束。
相关文章
相关标签/搜索