新特性
1.现在,结构的成员初始化程序为包含默认表达式的变量提供默认值。
struct Dog {
var name = "Generic dog name"
var age = 0
// The synthesized memberwise initializer
init(name: String = "Generic dog name", age: Int = 0)
}
let sparky = Dog(name: "Sparky") // Dog(name: "Sparky", age: 0)
2.现在可以使用类型别名声明@autoclosure参数。
class Foo {
typealias FooClosure = () -> String
func fooFunction(closure: @autoclosure FooClosure) {}
}
3.在类中使用@objc属性声明的方法现在可以返回Self.
class MyClass: NSObject {
@objc func clone() -> Self { return self }
}
4.键路径表达式现在可以包含对元组元素的引用.
5.接受Any类型的单参数函数不再优先于其他函数.
6.现在完全实现了元组类型之间的转换。 以前,以下将诊断错误。
let values: (Int, Int) = (10, 15)
let converted: (Int?, Any) = values
7.你现在可以声明和使用类型下标,就像类型属性和类型方法一样。 通过将static 或 在类中,类修饰符应用于下标声明来声明一个.
// Declare a type with a static subscript:
enum ProcessEnvironment {
static subscript(name: String) -> String? {
get { getenv(name) }
set { setenv(name, to: newValue) }
}
}
// Use it with any of these syntaxes:
ProcessEnvironment["PATH"]! += ":/usr/local/bin"
ProcessEnvironment["PATH"]! += ":/usr/local/bin"
someVarOfProcessEnvironmentDotType["PATH"]! += ":/usr/local/bin"
8.类型下标也可以与动态成员查找一起使用以创建动态类型属性。
// Declare a type with a static subscript:
@dynamicMemberLookup
enum ProcessEnvironment {
// …As above…
static subscript(dynamicMember name: String) -> String? {
get { self[name] }
set { self[name] = newValue }
}
}
// Now you can use property syntax with ProcessEnvironment:
ProcessEnvironment.PATH! += ":/usr/local/bin"
ProcessEnvironment.self.PATH! += ":/usr/local/bin"
someVarOfProcessEnvironmentDotType.PATH! += ":/usr/local/bin"
9.将Optional.none分配给也具有none案例的枚举,或者将此类枚举与Optional.none进行比较,现在会产生警告。 这样的表达式会产生歧义,因为编译器选择Optional.none而不是由您自己的枚举定义的none案例。
enum Foo { case none }
// Assigned Optional.none instead of Foo.none.
let foo: Foo? = .none
// Comparing with Optional.none instead of Foo.none.
let isEqual = foo == .none
编译器提供警告以及fix-it,用Optional.none或Foo.none替换.none以解决歧义。
10.函数现在可以通过声明它符合的协议来隐藏它们的具体返回类型,而不是指定确切的返回类型:
func makeACollection() -> some Collection {
return [1, 2, 3]
}
调用该函数的代码可以使用协议的接口,但不能查看基础类型。
11.枚举案例现在可以与可选枚举匹配,而不需要在模式结尾处使用“?”。
enum Foo { case zero, one }
let foo: Foo? = .zero
switch foo {
case .zero: break
case .one: break
case .none: break
}
12.现有的@dynamicMemberLookup属性现在支持键入的键路径实现。
struct Point {
var x, y: Int
}
@dynamicMemberLookup
struct Box<T> {
var v: T
init(_ v: T) {
self.v = v
}
subscript<U>(dynamicMember member: KeyPath<T, U>) -> U {
get { return v[keyPath: member] }
}
}
var box = Box(Point(x: 0, y: 0))
_ = box.x
13.你现在可以使用Self表达式来引用内部结构,枚举和类声明中最内部的名义类型。 例如,此结构中的两个方法声明是等效的:
struct Box<Value> {
func transform1() -> Self { return self }
func transform2() -> Box<Value> { return self }
}
在类中,Self是自我值的动态类型,和以前一样。 声明类型中对Self的现有限制仍然适用; 也就是说,Self只能作为方法的返回类型出现。 但是,Self现在可以在方法体内使用而没有限制。
14.Array和ContiguousArray现在有init(unsafeUninitializedCapacity:initializingWith :)初始化程序,它提供对阵列未初始化存储的访问。
15.2 对于转义捕获输入输出参数或noescape类型值的闭包的限制,已经实现了更彻底的检查。 虽然大多数代码不受影响,但有一些边缘情况,Swift 5.0编译器接受违反这些限制的代码。
Swift 5.0编译器错误接受的无效代码示例是一个@escaping闭包,它调用一个引用外部作用域的输入输出参数的本地函数:
struct BadCaptureExample {
var escapingClosure: () -> ()
mutating func takesInOut(_ x: inout Int) {
func localFunction() {
x += 1
}
escapingClosure = { localFunction() }
}
}
编译器现在通过指出localFunction()对x的捕获无效来正确诊断上述代码,因为localFunction()是从@escaping闭包引用的。
这也解决了某些情况,即编译器错误地将某些代码诊断为无效,而实际上并未发生违反限制的情况。 例如:
func takesNoEscape(_ fn: () -> ()) {
func localFunction() {
fn()
}
{ localFunction() }()
}
更新:(beta 3)
- 现在可以使用结构和枚举的@frozen属性.
网友评论