新特性列表
1 序列化与反序列化
2 String的多行存储
3 key-value Coding的优化
4 Range单边界特性
5 Dictionary功能的优化
6 String是一个集合
序列化与反序列化
Swift4中新添加了Codable协议让你可以非常方便的对值类型进行序列化以及反序列化,而不用担心丢失。
方便对于数据类型和JSON进行相互转化。
过去进行序列化,对于一个类/结构体中的属性,通常需要一条一条进行转化,然后进入Swift4之后,可以省去这些繁琐的步骤。
var data: Data?
struct Student: Codable {
var name: String
var age: Int
}
let student1 = Student.init(name: "小明", age: 5)
let student2 = Student.init(name: "ericwang", age: 19)
let student3 = Student.init(name: "zhang", age: 8)
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(student1) {
//此时encoded为data类型
//对于类型内部的属性,swift会自动进行序列化,不需要额外的做事。
}
let decoder = JSONDecoder()
if let decoded = try? decoder.decode(Student.self, from: data!) {
//此时decoded为 Student类型。
print(decoded.name)
}
更多的细节部分我会开一个新章节讲。
String的多行存储
我是很喜欢这个特性
过去在Swift中,如果需要在字符串中进行换行,需要手动敲入\n
来进行换行。这让人读起来非常的不方便。但至少来说,它满足了用户换行的需求。
但是一直希望有类似于所见即所得这样的极致——怎么敲进去的,就怎么显示出来。Swift4满足了我这个需求。
使用"""
三个双引号进行字符串的标识
"""
I am very glad!
Thank you!
I love you !
"""
上面的代码会生成一个新的字符串,并在规定出添加换行符,非常便于用户读写。
需要注意的是:内容不能与"""
处于同一行,前后均是。
key-value Coding优化
Objective-C语言中非常棒的一个特性就是可以动态的索引一个属性。这主要是由于keypaths
,并不是直接访问数据——因为这并未直接进行读写,而是暂时性的存储以待后续使用。
如果以前没有使用过keypaths
,我将举例说明。
struct Son {
var name: String
var age: Int
}
struct Father {
var name: String
var age: Int
var son: Son
func getSon() {
print("\(name) is \(son.name)'s father")
}
}
let xiaoming = Son.init(name: "xiaoming", age: 5)
let laowang = Father.init(name: "laowang", age: 38, son: xiaoming)
let getSon = laowang.getSon // ()->()
getSon() // laowang is xiaoming's father
小科普
类型:规定了变量可以取的值得范围,以及该类型的值可以进行的操作
根据类型的值可以赋值的情况,可以把类型分为三类:
1.一级的(first class) 该等级的类型的值可以传给子程序作为参数、可以从子程序返回、可以赋值给变量。大多数程序设计语言里,整型、字符类型等简单类型都是一级的。
2.二级的(second class) 该等级类型的值可以传递给子程序作为参数,但是不能从子程序里返回,也不能赋值给变量。
3.三级的(third class) 该等级类型的值联作为参数传递也不行。
关于类型的详细分析
好,回到正题,swift中function就是一个first class。上方代码块中let getSon = laowang.getSon
就是建立一个对getSon()
方法的索引。后续我们可以随时进行访问。
但是,我们不能对一个具体的属性建立这样的索引。例如let name = laowang.name
,因为这相当与值类型的赋值,而非索引。
使用keypaths
可以解决上述的痛点。类似于let getSon = laowang.getSon
,如果拿到了索引就能获取当前的值,并且swift使用类型推断来保证你获取的是正确的类型。
keypaths
样式如下图所示,使用符号\
作为起始,后面也可以获得代码提示,相较于过去的字符串形式更加的安全。
let sonNameKeypath = \Son.name
let sonAgeKeypath = \Son.age
let name = xiaoming[keyPath: sonNameKeypath]
// 结果是 获得字符串 “xiaoming”
//keypath也可以进行连接 比如:
let fatherSonKeypath = \Father.son
let finalPath = fatherSonKeypath.appending(path: \.name)
laowang[keyPath: finalPath]
//结果是获取字符串 “小明“
Range单边界特性
举个例子
let array = ["1","2","3","4","5"]
let array1 = array[1...3] //["2", "3", "4"]
let array2 = array[...3] //["1", "2", "3", "4"]
let array3 = array[1...] // ["2", "3", "4", "5"]
let array4 = array[..<4] // ["1", "2", "3", "4"]
在swift4之前的版本中,我们主要使用Range的两个符号...
, ..<
分别表示一个区间的双闭区间和前开后闭区间。
但是在Swift4中加入了新的特性。在...
和..<
两个符号左侧空置时,表示左侧从起始点开始,如array2和array4。而对应的在右侧空置时,表示右侧终结点为整个序列的末尾,如array3。这在很大程度上也方便了开发者,尤其是对于String类型的Range进行操作时。
Dictionary功能的优化
Swift4中的字典型变得更加强大。
filter操作
在早起的Swift3中,对于一个Dictionary进行filter操作,返回的并不是一个Dictionary,而是一个元素为元组的Array。如下图示例,返回的类型为[(key: String, value: Int)]
这里你并不能使用
p["a"]
,因为p并不是一个字典型。正确的调用方法是p[0].value但是在Swift4之后,对这个问题进行了修正。返回的结果变为
["d": 4, "c": 3]
map与mapValues操作
此外,字典型的map函数返回的仍然为array类型,但是添加了一个新的方法mapValues
,满足了整个字典进行转换的需要
let dict = ["a":1,"b":2,"c":3,"d":4]
let a = dict.mapValues { value -> Int in
return value * 2
}
//a的输出为 ["b": 4, "a": 2, "d": 8, "c": 6]
Dictionary.init(grouping: , by: )
看到一个很有意思的特性,把Array的元素通过一定的逻辑进行分类,形成字典型。 看下面例子。
let cities = ["Shanghai": 24_256_800, "Karachi": 23_500_000,
"Beijing": 21_516_000, "Seoul": 9_995_000];
let groupedCities = Dictionary(grouping: cities.keys)
{ $0.characters.first! }
print(groupedCities)
//输出结果 ["B": ["Beijing"], "S": ["Shanghai", "Seoul"], "K":["Karachi"]]
ToBeContinue
String重新变为集合
Swift4中String类型又重新变为一个集合,这也就以为着,可以进行的操作又变多了:翻转
、轮寻
、‘map’、‘flatmap’等遍历操作。