博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Swift 4.1 的新特性
阅读量:7224 次
发布时间:2019-06-29

本文共 5431 字,大约阅读时间需要 18 分钟。

  • 苹果公司在 3.29 正式发布了正式版的Xcode 9.3Swift 4.1, 让我们看看Swift 4.1带来了哪些新功能和新亮点
  • 测试需要Xcode9.3, 请确保你的Xcode是最新的9.3版本
  • Swift 4.1Swift 4.0是源代码兼容的,所以如果你已经使用Xcode中的Swift Migrator将你的项目迁移到Swift 4.0,那么新特性不会破坏你的代码
  • 下面在Xcode9.3下新建一个Playground工程, 测试我们的代码

条件一致性(Conditional Conformance)

  • 条件一致性使类型参数满足特定条件的泛型类型的协议一致性
  • 在Swift 4中,如果数组、字典或者可选类型的元素类型遵循Equatable,你是可以在数组之间、字典之间和可选类型之间进行比较的, 如下示例:
// Int类型的数组let arr1 = [1, 2, 3]let arr2 = [1, 2, 3]print(arr1 == arr2)// 比较value值为Int的字典let dic1 = ["age": 19, "score": 60]let dic2 = ["age": 19, "score": 60]print(dic1 == dic2)// 比较Int?let age1 = dic1["age"]let age2 = dic2["age"]print(age1 == age2)/// 以上输出结果都是: true复制代码

这里如果我们把Int都换成Int?类型, 在Swift4.0中是不能编译通过的, 如下:

// Int类型的数组let arr1: [Int?] = [1, 2, 3]let arr2: [Int?] = [1, 2, 3]print(arr1 == arr2)// 比较value值为Int的字典let dic1: [String: Int?] = ["age": 19, "score": 60]let dic2: [String: Int?] = ["age": 19, "score": 60]print(dic1 == dic2)// 比较Int?let age1 = dic1["age"]let age2 = dic2["age"]print(age1 == age2)复制代码
  • 在这些实例中, 我们用==测试相等性, 在Swift4.0中, Int类型遵循Equatable协议, 可以比较, 但是Int?类型却没有遵循Equatable协议
  • 但是在Swift4.1中, 完美的解决了这个问题, 上述代码可比那已通过, 且都输出: true
  • Swift 4.0[Set<Int>]之间可以直接对比,但是[[Int]]不能。现在Swift 4.1中,[[Int]]也能直接对比
  • 总的来说,Swift 4.1ArrayDictionaryOptional,只要他们的元素都遵循了EquatableHashable,那么他们也遵循EquatableHashable

合成 EquatableHashable

  • 如果对象相等,则这两个对象的 hash 值一定相等
  • 如果两个对象 hash 值相等,这两个对象不一定相等。
  • SwiftHashable 一定是 Equatable,因为前者继承了后者。 在Swift 4中,若遵循Equatable协议的时候,我们必须实现Equatable协议的==方法, Equatable协议如下:
public protocol Equatable {    /// Returns a Boolean value indicating whether two values are equal.    ///    /// Equality is the inverse of inequality. For any values `a` and `b`,    /// `a == b` implies that `a != b` is `false`.    ///    /// - Parameters:    ///   - lhs: A value to compare.    ///   - rhs: Another value to compare.    public static func == (lhs: Self, rhs: Self) -> Bool}复制代码

在Swift4.0中, 必须实现Equatable协议的方法

struct Name: Equatable {    var name1 = "name1"    var name2 = "name2"        static func == (lhs: Name, rhs: Name) -> Bool {        return lhs.name1 == rhs.name1 &&            lhs.name2 == rhs.name2    }}复制代码

Swift 4.1,只需要加上Equatable即可, 不需要实现任何协议方法

struct Name: Equatable {    var name1 = "name1"    var name2 = "name2"    }复制代码

JSON编码时支持Camel CaseSnake Case之间的转换

  • Swift 4.0引入了Codable,但是有个麻烦的问题:如果JSON数据的key命名格式是snake_case的话,我们必须创建自己的CodingKeys来告诉苹果怎么转换。在Swift 4.0
  • 但是在Swift 4.1中,苹果给JSONDecoder引入了一个属性keyDecodingStrategy;对应的JSONEncoder引入了一个属性keyEncodingStrategy。这样我们就不需要设置定义CodingKeys了。只需要在decoding的时候把keyDecodingStrategy设置为.convertFromSnakeCase;在encoding的时候把keyEncodingStrategy设置为.convertToSnakeCase
  • 下面是分别针对数组/字典/集合的解析形式
struct Student: Codable, Hashable {  let firstName: String  let averageGrade: Int}let cosmin = Student(firstName: "Cosmin", averageGrade: 10)let george = Student(firstName: "George", averageGrade: 9)let encoder = JSONEncoder()// Encode an Array of studentslet students = [cosmin, george]do {  try encoder.encode(students)} catch {  print("Failed encoding students array: \(error)")}// Encode a Dictionary with student valueslet studentsDictionary = ["Cosmin": cosmin, "George": george]do {  try encoder.encode(studentsDictionary)} catch {  print("Failed encoding students dictionary: \(error)")}// Encode a Set of studentslet studentsSet: Set = [cosmin, george]do {  try encoder.encode(studentsSet)} catch {  print("Failed encoding students set: \(error)")}// Encode an Optional Studentlet optionalStudent: Student? = cosmindo {  try encoder.encode(optionalStudent)} catch {  print("Failed encoding optional student: \(error)")}复制代码

Hashable Index Types(哈希化索引)

扩展 Key-path 表达式在标准库中的使用范围。让标准库中所有的索引类型都符合 Hashable 协议,这样,[Int]String 和所有其它标准集合使用 key-path 下标时,表现都是一样的

let swiftString2 = "one two three"let charact1 = \String.[swiftString2.startIndex]print(swiftString2[keyPath: charact1])let arr = [1, 2, 3, 4]let value2 = \[Int].[1]print(arr[keyPath: value2])//输出结果:o2复制代码

compactMap的用法

Swift 4.0中,我们经常使用flatMap来过滤nil,也可以进行降维操作, 详情可参考

let arr = [1, 2, nil, 3, 4, nil]let arr1 = arr.flatMap({ $0 })print(arr1)//这样使用会有类似的警告'flatMap' is deprecated: Please use compactMap(_:) for the case where closure returns an optional value Use 'compactMap(_:)' instead//Swift4.1中的用法let arr = [1, 2, nil, 3, 4, nil]let arr2 = arr.compactMap({ $0 })print(arr2)复制代码

主要是因为在Swift4.0flatMap有很多重载, 可能会引起歧义, 所以在Swift4.1中把flatMap重命名为compactMap

除了协议中的 weak 和 unowned。

  • 当你在Tune协议中定义了两个属性keypitch, pitch可能为nil, 所以你在协议中可以用weak修饰
  • 但是如果在协议本身中定义的话,weakunowned都没有实际意义, 所以在Swift4.1中就已经去掉了这些关键字, 并且在协议中使用这些关键字将会爆出警告
class Key {}class Pitch {}// Swift 4protocol Tune {    unowned var key: Key { get set }    weak var pitch: Pitch? { get set }}// Swift 4.1protocol Tune {    var key: Key { get set }    var pitch: Pitch? { get set }}复制代码

UnsafeMutableBufferPointer的改变

//Swift4.0let buffer = UnsafeMutableBufferPointer
(start: UnsafeMutablePointer
.allocate(capacity: 10), count: 10)let mutableBuffer = UnsafeMutableBufferPointer(start: UnsafeMutablePointer(mutating: buffer.baseAddress), count: buffer.count) //Swift4.1let buffer = UnsafeMutableBufferPointer
.allocate(capacity: 10)let mutableBuffer = UnsafeMutableBufferPointer(mutating: UnsafeBufferPointer(buffer))复制代码

相对Swift4.0的改变, Swift4.1这点改变键值太微不足道了, 传说中Swift5API会趋于稳定, 但是估计改变可能也是非常大的, 坐等Swift5发布...

参考文档

转载地址:http://fdkfm.baihongyu.com/

你可能感兴趣的文章
BOOST.ASIO源码剖析(一)
查看>>
过滤squidlog中各个链接的大小
查看>>
我的友情链接
查看>>
使用AnyChat如何实现任意两用户之间的音视频交互
查看>>
【个人小结】项目公共js的配置,解决不同页面多个配置修改的问题
查看>>
XAMP安装Apacher无法启动
查看>>
mongodb user
查看>>
ip地址子网划分
查看>>
Linux下快速搭建ntp时间同步服务器
查看>>
TouchEvent的传递过程学习笔记
查看>>
Android笔记--TCP Scoket(字符串收发)
查看>>
我的友情链接
查看>>
Hunt framework 2.0.0 发布,简单且高性能的 Web 服务框架
查看>>
数据库原理及应用(SQL Server 2016数据处理)【上海精品视频课程】
查看>>
MaxCompute表设计最佳实践
查看>>
Percona-Server-5.5.15源码安装
查看>>
容器安全拾遗 - Rootless Container初探
查看>>
LVS/NAT + keepalived负载均衡实现
查看>>
我的友情链接
查看>>
EAServer 的常做的配置
查看>>