Swift 4.0 | What's new in it?

文 / 菲拉兔

自己撸的图

要求:

  • Platform: iOS8.0+
  • Language: Swift4.0
  • Editor: Xcode9

Migeration

  • Xcode9中进行代码升级迁移也很方便,比较智能化。
    Edit/Convert

APIChanges

Strings
  • 字符串在Swift4中可以直接遍历其中的字符,而不是通过characters
// Swift4
let greeting = "Hello Swift4.0"
greeting.forEach{
    print($0)
}

// Before
let greeting = "Hello Swift"
greeting.characters.forEach{
    print($0)
}
  • 也可以使用Sequence和Collection协议的一些操作
let greeting = "Hello Swift"
// Swift4
greeting.count
greeting.isEmpty
greeting.dropFirst()

// Before
greeting.characters.count
  • 子串有了新的类型
let greeting = "Hello Swift"
let endIndex = greeting.index(greeting.startIndex, offsetBy: 5)
var hello = greeting[greeting.startIndex...endIndex] // `Hello`
type(of: hello) // Substring.Type

// 子串的操作和String一样
hello += " World"
let helloString = String(hello) // `Hello World`
Dictionary & Set
  • Swift4中对于Collection和Dictionary的转换有了更方便灵活的操作
  • Array和Dictionary转换。keys和values数量一致
let keys = ["name", "age", "isMale"]
let values = ["jack", 18, true] as [Any]

let dict = Dictionary(uniqueKeysWithValues: zip(keys, values))

// 结果
["name": "jack", "age": 18, "isMale": true]

  • 如果keys和values数量不一致,按数量少的匹配
let keys = ["name", "age", "isMale"]
let values = ["jack", 18] as [Any]

// 结果
["name": "jack", "age": 18]
Dictionary Default Values
  • 有时会碰到字典中的值为nil时,需要设置为默认的值,但在Swift4中有了新的方式
let dict = ["name": nil, "age": Optional(18)]
// Before Swift4
let name = dict["name"] ?? "Unkown Name"
let nickname = dict["nickname"] ?? "Unkown NickName"

// In Swift4
// 没有找到key值时,value为default值
let nickname = dict["nickname", default: "Unkown NickName"]
Dictionary Grouping
  • 这个感觉很有用,比如统计一个单词的各个字母出现的次数
let grouped = Dictionary.init(grouping: "Hello World", by: { $0 })
grouped.keys.forEach { print("\($0) : \(grouped[$0]!.count)") }

//结果:
H : 1
r : 1
e : 1
o : 2
l : 3
  : 1
W : 1
d : 1
Private Access Modifier
  • Swift4中private属性在extension中可以访问
struct Person{
    private let name: String
    
    init(name: String) {
        self.name = name
    }
}

extension Person{
    func call(somebodyWith name: String) {
        if name == self.name{
            print("I am!")
        }
        else{
            print("\(name) is not me!")
        }
    }
}
let xiaoming = Person(name: "Xiao Ming")
xiaoming.call(somebodyWith: "Xiao Ming")

API Additions

Archival and Serialization
  • Swift4以前,通常要对一个object进行归/解档的话,首先要让对象成为NSObject的子对象,并遵守NSCoding协议,然后进行一系列的处理;
  • Swift4中,通常只需要让object和其子属性类型遵守Codable协议即可
struct Person: CustomStringConvertible, Codable{
    enum Role: String, Codable {
        case student, teacher
    }
    
    var name: String
    var age: Int
    var role: Role
    
    var description: String{
        return "(name: \(name), age: \(age), role: \(role.rawValue))"
    }
}

let student = Person(name: "Xiao Ming", age: 18, role: .student)
// 编码
guard let data = try? JSONEncoder().encode(student),
      let jsonText = String(data: data, encoding: .utf8) else{
    fatalError("JSON Object Encode Failed")
}
print(jsonText)
// 结果:
{"name":"Xiao Ming","age":18,"role":"student"}

// 解码
guard let xiaoming = try? JSONDecoder().decode(Person.self, from: data) else{
    fatalError("JSON Object Decode Failed")
}
print(xiaoming)
// 结果:
(name: Xiao Ming, age: 18, role: student)
Key-Value Coding
  • KVO在OC中比较一般用来深层遍历对象的属性,或设置新的值。在Swift4中,它称为一种类型WritableKeyPath<Any, Any>而不是以前的字符串,表现方式也有了全新的形式:\Any.propertyName
struct School{
    var name: String
    var address: String
}

struct Person{
    enum Role: String {
        case student, teacher
    }
    
    var name: String
    var age: Int
    var role: Role
    var school: School
}

var student = Person(name: "Xiao Ming", age: 18, role: .student, school: School(name: "BISTU", address: "Beijing"))

// 创建name key path实例
let nameKeyPath = \Person.name // `WritableKeyPath<Person, String>`

// 取值
let name = student[keyPath: nameKeyPath] // `Xiao Ming`

// 也可以进一步取值
let schoolName = student[keyPath: \Person.school].name // `BISTU`

// 赋值
student[keyPath: \Person.school].name = "TingHua" // `TingHua`
Multi-line String Literals
  • Swift4中终于支持多行字符串了,这在写JSON/XML/HTML等格式化的文本时,显得尤为方便。Swift4中用""" xxx """三个双引号表示多行文本。
// String类型
let JSONText = """
[
    {
        "name": "Banana",
        "points": 200,
        "description": "A banana grown in Ecuador."
    }
]
"""
One-Sided Ranges
  • 单边范围。在Swift4以前,定义一个范围Range,基本都需要指定startIndex和endIndex,但在Swift4中,系统可以自动推断该range的start/endIndex,减少了冗余,提高了可读性。
let numbers = [1, 2, 3, 4]
numbers[1...]
numbers[..<2]
numbers[1..<2]
  • 也允许你定义无限大的range
let infiniteRange = 1... // CountablePartialRangeFrom<Int>类型
infiniteRange.forEach{
    print($0)
}
  • 单边range在模式匹配中的使用
func markLevelWith(score: UInt){
    switch score {
    case 90...100:
        print("A")
    case 80..<90:
        print("B")
    case 60..<80:
        print("C")
    case ..<60:
        print("D")
    default:
        print("Your Score is Over the Top Level!")
    }
}
markLevelWith(score: 33) // D
Generic Subscripts
  • Swift4中,你可以为类型定义一个可以通用任何key的下标算式。
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 person = GenericDictionary(data: ["name": "Xiao Ming", "age": 18])
let name: String? = person["name"] // `Xiao Ming`
let age: Int? = person["age"] // `18`
  • 而且还可以实现多个key的组合下标
extension GenericDictionary{
    subscript<Keys: Sequence>(keys: Keys) -> [Value] where Keys.Iterator.Element == Key{
        var values = [Value]()
        for key in keys{
            if let value = data[key] {
                values.append(value)
            }
        }
        return values
    }
}

person[["name", "age"]] // ["Xiao Ming", 18]
MutableCollection.swapAt(::)
  • 可变集合类型的值交换方法
// 简单来说
var info = person[["name", "age"]] // ["Xiao Ming", 18]
info.swapAt(0, 1) // [18, "Xiao Ming"]
Associated Type Constraints
  • 关联类型约束
protocol MyProtocol {
  associatedtype Element
  associatedtype SubSequence : Sequence where SubSequence.Iterator.Element == Iterator.Element
}

Class & Protocol

协议组合
  • 在Swift4中一个对象的属性可以遵守多个协议,用&组合
protocol Speakable{ }
protocol Eatable{ }
protocol Loveable{ }
protocol Moveable{ }

class Person: Speakable, Eatable, Loveable, Moveable{
}

class Pet{
    var master: (Loveable & Moveable)?
}

let cat = Pet()
cat.master = Person()
Limiting @objc Inference
  • 限制@objc的接口。Swift4中系统做了一些限制,避免了一些在使用该标记时给项目带来的风险和增加二进制文件的体积。
NSNumber Bridging
  • NSNumber和基本数据类型的转换,在Swift4中也进行了简化,只有一种统一的转换方式
let number = NSNumber(value: 10)
let ok = NSNumber(value: true)
  • 也修复了一些操作运算的错误
let n = NSNumber(value: 999)
let v = n as? UInt8 // Swift 4: nil, Swift 3: 231

let x = 2^8 // 10

Swift Package Manager

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

推荐阅读更多精彩内容