最新在寫(xiě)swift的時(shí)候感覺(jué)不怎么順手碍扔,于是把新特性看了一遍苏遥,順便做一下筆記氓栈,加深一下記憶。
1拐云、語(yǔ)法改進(jìn)
extesion 中可以訪問(wèn)private的屬性
例:
struct Date: Equatable,Comparable {
private let secondsSinceReferenceDate: Double
static func ==(lhs: Date, rhs: Date) -> Bool {
return lhs.secondsSinceReferenceDate == rhs.secondsSinceReferenceDate
}
static func <(lhs: Date, rhs: Date) -> Bool {
return lhs.secondsSinceReferenceDate < rhs.secondsSinceReferenceDate
}
}
這個(gè)是將Date實(shí)現(xiàn)Equatable罢猪,Comparable的協(xié)議。為了更swift話一下叉瘩,可以將代碼改造成膳帕。
struct Date {
private let secondsSinceReferenceDate: Double // 結(jié)構(gòu)體中定一個(gè)私有屬性
}
// 擴(kuò)展結(jié)構(gòu)體,實(shí)現(xiàn)Equatable,Equatable協(xié)議
extension Date: Equatable {
static func ==(lhs: Date, rhs: Date) -> Bool {
return lhs.secondsSinceReferenceDate == rhs.secondsSinceReferenceDate
}
}
extension Date: Comparable {
static func <(lhs: Date, rhs: Date) -> Bool {
return lhs.secondsSinceReferenceDate < rhs.secondsSinceReferenceDate
}
}
swift4能這樣調(diào)用房揭,但是swift3將會(huì)提示錯(cuò)誤备闲,要把Date中的private改成fileprivate晌端,這樣會(huì)把作用域變大,造成屬性的濫用恬砂。而swift4咧纠,就是將private的作用域變大,擴(kuò)展到extension中泻骤,這樣就不必更改屬性的作用域了漆羔。
類型+協(xié)議 生成的組合類型
protocol Shakeable {
func shake()
}
extension UIButton: Shakeable {
func shake() {
print("a")
}
}
extension UISlider: Shakeable {
func shake() {
print("b")
}
}
func shakeEm(controls: [UIControl & Shakeable]) {
for control in controls where control.isEnabled {
control.shake()
}
}
這樣就可以直接使用類型中遵循協(xié)議的方法,而不必要再判斷cotrol是否遵循這個(gè)協(xié)議狱掂,然后在as一下來(lái)調(diào)用協(xié)議中的方法演痒。
associatedtype 可以追加where的約束
protocol Shakeable {
associatedtype Element where Self.Element == Self.Iterator.Element
func shake()
}
這樣可以避免在使用Shakeable時(shí)多做一個(gè)類型判斷
key paths 語(yǔ)法的改變
因?yàn)橐郧暗膶?xiě)法,這個(gè)在swift4上總是寫(xiě)的不舒服趋惨。swift4創(chuàng)建一個(gè)keyPath要用\開(kāi)頭
\keyPath
swift3使用setValue來(lái)寫(xiě)
@objcMembers class Kid: NSObject {
dynamic var nickname: String = ""
dynamic var age: Double = 0.0
dynamic var friends: [Kid] = []
}
var ben = Kid(nickname: "Benji", age: 5.5)
let kidsNameKeyPath = #keyPath(Kid.nickname)
let name = ben.valueForKeyPath(kidsNameKeyPath)
ben.setValue("Ben", forKeyPath: kidsNameKeyPath)
而變成swift4就用了
struct Kid {
var nickname: String = ""
var age: Double = 0.0
var friends: [Kid] = []
}
var ben = Kid(nickname: "Benji", age: 8, friends: [])
let name = ben[keyPath: \Kid.nickname]
ben[keyPath: \Kid.nickname] = "BigBen"
不是很習(xí)慣鸟顺。
swift4的keyPath新特點(diǎn):
1、可以定義class器虾、struct讯嫂,而不必加上@objcMembers、dynamic的關(guān)鍵字
2兆沙、類型安全和類型推斷
3欧芽、可以用在所有的值類型上
下標(biāo)支持泛型
現(xiàn)在下標(biāo)用泛型不需要用as來(lái)轉(zhuǎn)換類型了
例:
struct GenericDictionary<Key: Hashable, Value> {
private var data: [Key: Value]
init(data: [Key: Value]) {
self.data = data
}
subscript<T>(key: Key) -> T? {
return data[key] as? T
}
}
let dictionary = GenericDictionary(data: ["Name" : "xx"])
let name: String? = dictionary["name"]
字符串
Unicode字符串在計(jì)算count時(shí)的正確性改善
var family = "??"
print(family.characters.count) // 1
去掉characters
現(xiàn)在string的某些屬性可以不用characters。但是自動(dòng)填充下有些加的characters的類型和不加的類型有些不同葛圃。
可以取單側(cè)邊界
新加語(yǔ)法糖...可以對(duì)字符串取單側(cè)邊界
let v = "hhgggdads"
let startSlicIndex = v.index(v.startIndex, offsetBy: 3)
let subvalue = v[startSlicIndex...]
String實(shí)現(xiàn)了Collection協(xié)議
因?yàn)閷?shí)現(xiàn)了collection協(xié)議千扔,所以現(xiàn)在可以調(diào)用collection 的方法
例:
//翻轉(zhuǎn)字符串
let abc: String = "abc"
print(String(abc.reversed()))
//遍歷
for i in abc {
print(i)
}
//map
_ = abc.map {
print($0.description)
}
//filter
let filterd = abc.filter { $0 == "b"}
//reduce
let result = abc.reduce("1") { (result, c) -> String in
print(result)
print(c)
return result + String(c)
}
print(result)
Substring
在 Swift 中,String 的背后有個(gè) Owner Object 來(lái)跟蹤和管理這個(gè) String库正,String 對(duì)象在內(nèi)存中的存儲(chǔ)由內(nèi)存其實(shí)地址曲楚、字符數(shù)、指向 Owner Object 指針組成诀诊。Owner Object 指針指向 Owner Object 對(duì)象洞渤,Owner Object 對(duì)象持有 String Buffer。當(dāng)對(duì) String 做取子字符串操作時(shí)属瓣,子字符串的 Owner Object 指針會(huì)和原字符串指向同一個(gè)對(duì)象,因此子字符串的 Owner Object 會(huì)持有原 String 的 Buffer讯柔。當(dāng)原字符串銷毀時(shí)抡蛙,由于原字符串的 Buffer 被子字符串的 Owner Object 持有了,原字符串 Buffer 并不會(huì)釋放魂迄,造成極大的內(nèi)存浪費(fèi)粗截。
在 Swift 4 中,做取子串操作的結(jié)果是一個(gè) Substring 類型捣炬,它無(wú)法直接賦值給需要 String 類型的地方熊昌。必須用 String() 包一層绽榛,系統(tǒng)會(huì)通過(guò)復(fù)制創(chuàng)建出一個(gè)新的字符串對(duì)象,這樣原字符串在銷毀時(shí)婿屹,原字符串的 Buffer 就可以完全釋放了灭美。
多行字符串字面量
swift4可以把字符串寫(xiě)在一對(duì)"""中,這樣字符串就可以寫(xiě)成多行昂利。
let joke = """
Q: Why does have in their name?
A: I don't know, why does have s in their name?
Q: Because otherwise they'd be called (punchline).
"""
標(biāo)準(zhǔn)庫(kù)
Encoding and Decoding
swift4中引入Codable來(lái)解決對(duì)象持久話問(wèn)題
struct Language: Codable {
var name: String
var version: Int
}
將language對(duì)象的實(shí)例持久化届腐,只要language遵循Codable協(xié)議就好,然后encode成json或者PropertyList
//encode
let swift = Language(name:"swift",version: 4)
if let encode = try? JSONEncoder().encode(swift){
// 保存encode
}
//decode
if let decoded = try? JSONDecoder().decode(Language.self, from: encoded) {
print(decoded.name)
}
sequence的改進(jìn)
protocol Sequence {
associatedtype Element
associatedtype Iterator: IteratorProtocol where Iterator.Element == Element
func makeIterator() -> Iterator
}
swift4的associatedtype支持追加where語(yǔ)句蜂奸,這樣獲取Sequence的元素類型可以不用 Iterator.Element犁苏,而是直接取 Element。
Protocol-oriented integers
整數(shù)類型符合的協(xié)議有修改扩所,新增了 FixedWidthInteger 等協(xié)議围详,具體的協(xié)議繼承關(guān)系如下
+-------------+ +-------------+
+------>+ Numeric | | Comparable |
| | (+,-,*) | | (==,<,>,...)|
| +------------++ +---+---------+
| ^ ^
+-------+------------+ | |
| SignedNumeric | +-+-------+-----------+
| (unary -) | | BinaryInteger |
+------+-------------+ |(words,%,bitwise,...)|
^ ++---+-----+----------+
| +-----------^ ^ ^---------------+
| | | |
+------+---------++ +---------+---------------+ +--+----------------+
| SignedInteger | | FixedWidthInteger | | UnsignedInteger |
| | |(endianness,overflow,...)| | |
+---------------+-+ +-+--------------------+--+ +-+-----------------+
^ ^ ^ ^
| | | |
| | | |
++--------+-+ +-+-------+-+
|Int family |-+ |UInt family|-+
+-----------+ | +-----------+ |
+-----------+ +-----------+
ps:個(gè)人也不是很理解,只是參看了文檔上的解釋祖屏。
Dictionary and Set enhancements
dictionary和set增強(qiáng)的功能:
1短曾、通過(guò)Sequence來(lái)初始化
2、可以包含重復(fù)的Key
3赐劣、Filter的結(jié)果的類型和原類型一致
4嫉拐、dictionary的mapValues方法
5、dictionary的默認(rèn)值
6魁兼、dictionary可以分組
7婉徘、dictionary可以翻轉(zhuǎn)
NSNumber bridging and Numeric types
let n = NSNumber(value: 999)
let v = n as? UInt8 // Swift 4: nil, Swift 3: 231
swift4中,把值為999的NSNumber轉(zhuǎn)換為UInt8后會(huì)返回nil咐汞,而swift3會(huì)返回231這個(gè)意外的值
MutableCollection.swapAt(::)
MutableCollection 現(xiàn)在有了一個(gè)新方法 swapAt(::) 用來(lái)交換兩個(gè)位置的值
var mutableArray = [1, 2, 3, 4]
mutableArray.swapAt(1, 2)
print(mutableArray)
// 打印結(jié)果:[1, 3, 2, 4]
工程上
預(yù)編譯 Bridging Headers 文件
編譯器會(huì)預(yù)編譯 Bridging Headers 文件盖呼,這樣就不要在編譯的時(shí)候每次都編譯oc的頭文件生成的swift文件,從加快了編譯速度化撕。
Indexing 可以在編譯的同時(shí)進(jìn)行
用 Swift 開(kāi)發(fā)項(xiàng)目時(shí)几晤,近幾個(gè)版本的 Xcode 進(jìn)行 Indexing 的速度慢的令人發(fā)指。Xcode 9 和 Swift 4 在這方面做了優(yōu)化植阴,可以在編譯的同時(shí)進(jìn)行 Indexing蟹瘾,一般編譯結(jié)束后 Indexing 也會(huì)同時(shí)完成
COW Existential Containers
Swift 中有個(gè)東西叫 Existential Containers,它用來(lái)保存未知類型的值掠手,它的內(nèi)部是一個(gè) Inline value buffer憾朴,如果 Inline value buffer 中的值占用空間很大時(shí),這個(gè)值會(huì)被分配在堆上喷鸽,然而在堆上分配內(nèi)存是一個(gè)性能比較慢的操作众雷。
Swift 4 中為了優(yōu)化性能引入了 COW Existential Containers,這里的 COW 就代表 “Copy-On-Write”,當(dāng)存在多個(gè)相同的值時(shí)砾省,他們會(huì)共用 buffer 上的空間鸡岗,直到某個(gè)值被修改時(shí),這個(gè)被修改的值才會(huì)被拷貝一份并分配內(nèi)存空間编兄。
移除未調(diào)用的協(xié)議實(shí)現(xiàn)
struct Date {
private let secondsSinceReferenceDate: Double
}
extension Date: Equatable {
static func ==(lhs: Date, rhs: Date) -> Bool {
return lhs.secondsSinceReferenceDate == rhs.secondsSinceReferenceDate
}
}
extension Date: Comparable {
static func <(lhs: Date, rhs: Date) -> Bool {
return lhs.secondsSinceReferenceDate < rhs.secondsSinceReferenceDate
}
}
上面的例子轩性,Date 實(shí)現(xiàn)了 Equatable 和 Comparable 協(xié)議。編譯時(shí)如果編譯器發(fā)現(xiàn)沒(méi)有任何地方調(diào)用了對(duì) Date 進(jìn)行大小比較的方法翻诉,編譯器會(huì)移除 Comparable 協(xié)議的實(shí)現(xiàn)炮姨,來(lái)達(dá)到減小包大小的目的。
減少隱式 @objc 自動(dòng)推斷
在 Swift 4 中碰煌,隱式 @objc 自動(dòng)推斷只會(huì)發(fā)生在很少的當(dāng)必須要使用 @objc 的情況舒岸,比如:
復(fù)寫(xiě)父類的 Objective-C 方法
符合一個(gè) Objective-C 的協(xié)議
其它大多數(shù)地方必須手工顯示的加上 @objc。
減少了隱式 @objc 自動(dòng)推斷后芦圾,Apple Music app 的包大小減少了 5.7%蛾派。
OK筆記就到這,下面是參考資料:
WWDC 2017 Session 402 《What’s New in Swift》
WWDC 2017 Session 212 《What’s New in Foundation》
WWDC 2017 Session 102 《Platforms State of the Union》
《Swift Language Programming (Swift 4.0)》
https://github.com/apple/swift-evolution
https://github.com/ole/whats-new-in-swift-4
https://www.raywenderlich.com/163857/whats-new-swift-4
https://www.hackingwithswift.com/swift4