xcode swift 闭包不提示扩号内容_今年的 Swift,有哪些新的东西呢?

fa47e0e910c2a08e21a44b4ca2361047.png

苹果官方在美国当地时间 9.20 在 Swift 官方正式官宣了 Swift 5.1。Swift 5.1在Swift 5的基础上扩展了语言的稳定功能。不过等等,本文不是对官宣文档的整理,而是整理自 Xcode 11 release note。

Xcode 11 中对 Swift 的支持也有部分更新,包括一些新特性和修复了一些问题。我们在此将与 Swift 相关的内容独立出来。主要是 Swift 语言本身和 Swift Package 两部分。SwiftUI 还处在不断的更新中,所以在此也不提及。而 Swift 编译器并没有太多的更新。

如果内容上有问题,可以在留言区留言指出,这样大家都可以看到问题,在此感谢。

Swift

• 现在可以使用结构和枚举的 @frozen 属性。

• 结构的成员初始化器为包含默认表达式的参数提供默认值。

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)

• 现在可以使用类型别名声明 @autoclosure 参数。 

class Foo {
typealias FooClosure = () -> String
func fooFunction(closure: @autoclosure FooClosure) {}
}

• 在类中使用 @objc 属性声明的方法现在可以返回 Self。

class MyClass: NSObject {
@objc func clone() -> Self { return self }
}

• Key path 表达式现在可以包含对元组元素的引用。

• 接受 Any 类型的单参数函数不再优先于其他函数。

• 现在完全实现了元组类型之间的转换。在以前,以下代码是有问题的:

let values: (Int, Int) = (10, 15)
let converted: (Int?, Any) = values

• 现在可以声明和使用类型下标,就像类型属性和类型方法一样。通过将 static 或在类中使用 class 修饰符应用于下标声明来声明一个。

// 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"

类型下标也可以与动态成员查找一起使用以创建动态类型属性。

// 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"

• 将 Optional.none 分配给具有 none 的枚举,或者将此类枚举与 Optional.none 进行比较,现在会产生警告。这样的表达式会产生歧义,因为编译器选择 Optional.none 而不是由您自己的枚举定义的 none case。

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 以解决歧义。

• 函数现在可以通过声明它符合的协议来隐藏它们的具体返回类型,而不是指定确切的返回类型:

func makeACollection() -> some Collection {
return [1, 2, 3]
}

调用该函数的代码可以使用协议的接口,但不能查看基础类型。

• Enum case 现在可以与可选枚举匹配,而不需要在模式结尾处使用“?”。

enum Foo { case zero, one }

let foo: Foo? = .zero

switch foo {
case .zero: break
case .one: break
case .none: break
}

• 现有的 @dynamicMemberLookup 属性现在支持类型化的 key path 实现。

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

• 您现在可以使用 Self 表达式来引用结构,枚举和类声明自身的类型。例如,此结构中的两个方法声明是等效的:

struct Box<Value> {
func transform1() -> Self { return self }
func transform2() -> Box<Value> { return self }
}

在类中,Self 是 self 值的动态类型,和以前一样。声明类型中对 Self 的现有限制仍然适用;也就是说,Self 只能作为方法的返回类型出现。但是,Self 现在可以在方法体内使用而没有限制。 

• Array 和 ContiguousArray 现在有 init(unsafeUninitializedCapacity:initializingWith:) 初始化程序,它提供对数组未初始化存储的访问。

• 对于转义捕获 in-out 参数或 noescape 类型值的闭包的限制,已经实现了更彻底的检查。虽然大多数代码不受影响,但有一些边缘情况,Swift 5.0 编译器接受违反这些限制的代码。

Swift 5.0 编译器错误接受的无效代码的示例是一个 @escaping 闭包,它调用一个引用外部作用域的 in-out 参数的本地函数:

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() }()
}

已解决的问题

• 不再允许重复的元组元素标签,因为它会导致不正确的行为。

以下现在被诊断为错误:

let dupLabels: (foo: Int, foo: Int) = (foo: 1, foo: 2)
enum Foo {
case bar(x: Int, x: Int)
}
let f: Foo = .bar(x: 0, x: 1)

只要内部标签不同,您在声明函数和下标时仍可以使用重复标签。例如:

func foo(bar x: Int, bar y: Int) {}
subscript(a x: Int, a y: Int) -> Int {}

• 现在,静态库在链接期间总是完全强制加载,修复了大多数“unable to demangle”的运行时错误。

• weak 和 unowned 存储属性不再影响 Equatable 或 Hashable 一致性的自动合成。

• 如果崩溃日志中的符号未正确解码,请运行 swift-demangle 命令并传入崩溃日志的内容。

• 如果类型与其包含模块具有相同的名称,则从模块接口导入该模块可以正常工作。

Swift Packages

• Xcode 现在支持使用 Swift packages 创建和使用,以及添加,删除和管理包依赖项。Xcode 中的包管理支持构建在开源 Swift Package Manager 项目之上的项目。

已解决问题

• 无论 Package.swift 清单文件中声明的 target 名称在大小写上与该 target 的目录名是否相同,Code completion 均适用于 Swift package 目标。

• 在 Swift package 的 C 系列 target 中添加新文件不会创建扩展名为 .swift 的文件。

• 使用 unsafeFlags 构建设置的 Swift package 不能用作依赖项。


推荐阅读
• iOS 13 正式发布,来看看有哪些 API 变动 • iOS 实现远程推送通知国际化 • iOS APP内存优化记录 • 一个好用的 Xcode 扩展:GHWXcodeExtension • 简谈 Machine Code Layout
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值