Swift 4.1 的新特性

  • 原文博客地址: Swift 4.1 的新特性
  • 苹果公司在 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)

  • 条件一致性使类型参数满足特定条件的泛型类型的协议一致性 [ SE-0143 ]
  • 在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 students
let students = [cosmin, george]
do {
  try encoder.encode(students)
} catch {
  print("Failed encoding students array: \(error)")
}

// Encode a Dictionary with student values
let studentsDictionary = ["Cosmin": cosmin, "George": george]
do {
  try encoder.encode(studentsDictionary)
} catch {
  print("Failed encoding students dictionary: \(error)")
}

// Encode a Set of students
let studentsSet: Set = [cosmin, george]
do {
  try encoder.encode(studentsSet)
} catch {
  print("Failed encoding students set: \(error)")
}

// Encode an Optional Student
let optionalStudent: Student? = cosmin
do {
  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])

//输出结果:
o
2

compactMap的用法

Swift 4.0中,我们经常使用flatMap来过滤nil,也可以进行降维操作, 详情可参考Swift函数式编程之高级用法

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 4
protocol Tune {
    unowned var key: Key { get set }
    weak var pitch: Pitch? { get set }
}
// Swift 4.1
protocol Tune {
    var key: Key { get set }
    var pitch: Pitch? { get set }
}

UnsafeMutableBufferPointer的改变

//Swift4.0
let buffer = UnsafeMutableBufferPointer<Int>(start: UnsafeMutablePointer<Int>.allocate(capacity: 10), 
                                             count: 10)
let mutableBuffer = UnsafeMutableBufferPointer(start: UnsafeMutablePointer(mutating: buffer.baseAddress), 
                                               count: buffer.count)
                                               
//Swift4.1
let buffer = UnsafeMutableBufferPointer<Int>.allocate(capacity: 10)
let mutableBuffer = UnsafeMutableBufferPointer(mutating: UnsafeBufferPointer(buffer))

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

参考文档

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,825评论 4 377
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,887评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,425评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,801评论 0 224
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,252评论 3 299
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,089评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,216评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 31,005评论 0 215
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,747评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,883评论 2 255
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,354评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,694评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,406评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,222评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,242评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,017评论 2 281

推荐阅读更多精彩内容