Xcode 10
CaseInterable协议
1 2 3 4 5 6 | enum NetState: CaseIterable { case wifi case hotWifi case mobile case none } |
之后我们在其他地方调用改枚举时就可以获取到allCase属性, 如下
1 2 3 4 5 6 7 8 9 10 11 12 | print(NetState.allCases) print( "case个数: " + "\(NetState.allCases.count)" ) for item in NetState.allCases { print(item) } // 输出结果: [__lldb_expr_9.NetState.wifi, __lldb_expr_9.NetState.hotWifi, __lldb_expr_9.NetState.mobile, __lldb_expr_9.NetState.none] case 个数: 4 wifi hotWifi mobile none |
这个allCases的自动合成仅替换没有参数的case值, 但是如果需要你需要所有case值, 可以重写allCases属性自己添加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | enum FoodKind: CaseIterable { //此处, 必须重写allCases属性, 否则报错 static var allCases: [FoodKind] { return [.apple, .pear, .orange(look: false )] } case apple case pear case orange(look: Bool) } for item in FoodKind.allCases { print(item) } /* * 输出结果: apple pear orange(look: false) */ |
如果有枚举项标记为unavailable,则默认无法合成allCases,只能依靠自己来手动合成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | enum CarKind: CaseIterable { //当有unavailable修饰的case值, 也必须重写allCase属性 static var allCases: [CarKind] { return [.bwm, .ford] } case bwm case ford @available(*, unavailable) case toyota } for item in CarKind.allCases { print(item) } /* 输出结果: bwm ford */ |
#warning和#error编译指令
image
#warning和#error可以和已存的#if编译指令共同使用,并且只有在条件为true时才会激活。例如:
1 2 3 | # if os(macOS) #error( "MyLibrary is not supported on macOS." ) #endif |
动态成员查找
1 2 3 4 5 6 | struct Titan { subscript(dynamicMember member: String ) -> String { let properties = [ "name" : "Titanjun" , "city" : "Hang" ] return properties[member, default : "0" ] //默认值 } } |
1 2 3 4 5 6 7 8 | let titan = Titan() print(titan.name) print(titan.city) print(titan.age) // 输出: Titanjun Hang 0 |
处理多种不同的类型
1 2 3 4 5 6 7 8 9 10 11 12 | @dynamicMemberLookup struct Titan { subscript(dynamicMember member: String ) -> String { let properties = [ "name" : "Titanjun" , "city" : "Hang" ] return properties[member, default : "0" ] //默认值 } subscript(dynamicMember member: String ) -> Int { let properties = [ "age" : 20 , "source" : 99 ] return properties[member, default : 0 ] //默认值 } } |
需要注意的是: 这里取值的时候, 必须注明所取得值的类型
1 2 3 4 5 6 7 8 9 10 | let titan = Titan() let name: String = titan.name let city: String = titan.city let age: Int = titan.age let jun: String = titan.jun print(jun) print( "name = \(name), city = \(city), age = \(age)" ) //输出: 0 name = Titanjuun, city = Hang, age = 20 |
增强的条件一致性
条件一致性在Swift 4.1中引入,一个类型的所有元素如果符合Hashable协议,则类型自动符合Hashable协议
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //定义Purchaseable协议 protocol Purchaseable { func buy() } //定义一个符合该协议的结构体 struct Book: Purchaseable { func buy() { print( "You bought a book" ) } } //数组遵循该协议, 并且每一个元素也遵循该协议 extension Array : Purchaseable where Element: Purchaseable { func buy() { for item in self { item.buy() } } } |
下面我们在Swift 4.1中运行如下代码, 会发现崩溃
1 2 3 4 5 | let items: Any = [Book(), Book(), Book()] if let books = items as ? Purchaseable { books.buy() } |
本地集合元素移除
SE-0197介绍一个新的removeAll(where:)方法, 高效地执行根据条件删除操作
1 2 3 4 | var pythons = [ "John" , "Michael" , "Graham" , "Terry" , "Eric" , "Terry" ] pythons.removeAll { $ 0 .hasPrefix( "Terry" ) } print(pythons) //输出: ["John", "Michael", "Graham", "Eric"] |
对比filter过滤方法
1 2 3 | var python2 = [ "John" , "Michael" , "Graham" , "Terry" , "Eric" , "Terry" ] python2 = python2.filter { !$ 0 .hasPrefix( "Terry" ) } print(python2) |
这并不是非常有效地使用内存,它指定了你不想要的东西,而不是你想要的东西
随机数字的生成和洗牌
1 2 3 4 5 | let ranInt = Int.random( in : 0 ..< 5 ) let ranFloat = Float.random( in : 0 ..< 5 ) let ranDouble = Double.random( in : 0 ..< 5 ) let ranCGFloat = CGFloat.random( in : 0 ..< 5 ) let ranBOOL = Bool.random() |
对数组进行重新洗牌
SE-0202还支持使用新方法shuffle()和shuffled()方法对数组元素进行重新随机排序
1 2 3 4 5 | var albums = [ "Red" , "1989" , "Reputation" ] // 没有返回值 albums.shuffle() // 有返回值, 重新返回一个数组 let shuffled = albums.shuffled() |
获取数组中的一个随机元素
randomElement(): 数组的一个新方法, 如果数组部位空, 则返回数组中的一个随机元素, 否则返回nil
1 2 3 | if let random = albums.randomElement() { print( "The random album is \(random)." ) } |
更简单,更安全的哈希
1 2 3 4 5 6 7 | struct iPad: Hashable { var serialNumber: String var capacity: Int func hash(into hasher: inout Hasher) { hasher.combine(serialNumber) } } |
1 2 3 4 5 6 | let first = iPad(serialNumber: "12345" , capacity: 256 ) let second = iPad(serialNumber: "54321" , capacity: 512 ) var hasher = Hasher() hasher.combine(first) hasher.combine(second) let hash = hasher.finalize() |
检查序列元素是否符合条件
SE-0207提供了allSatisfy()一种检查序列中的所有元素是否满足条件的新方法
1 2 3 4 5 6 | //判断数组的所有元素是否全部大于85 let scores = [ 86 , 88 , 95 , 92 ] //返回一个BOOL let passed = scores.allSatisfy({ $ 0 > 85 }) print(passed) //输出: true |
布尔切换
SE-0199引入了一种新的toggle()方法, 可以将布尔值取反, 实现代码如下:
1 2 3 4 5 | extension Bool { mutating func toggle() { self = !self } } |
测试代码
1 2 3 4 | var isSwift = true //toggle函数没有返回值 isSwift.toggle() print(isSwift) |
1 2 3 4 5 6 7 8 | let a = [ 20 , 30 , 10 , 40 , 20 , 30 , 10 , 40 , 20 ] print(a.first(where: { $ 0 > 25 })) print(a.index(where: { $ 0 > 25 })) print(a.index(of: 10 )) //输出: 30 1 2 |
Swift 4.2中新增的last函数
1 2 3 4 5 6 7 8 | //在Swift4.1中 print((a.reversed().index(where: { $ 0 > 25 })?.base).map({ a.index(before: $ 0 ) })) //输出: 7 //Swift 4.2 //获取满足条件的元素 print(a.last(where: { $ 0 > 25 })) //40 //获取满足条件的元素的索引 print(a.lastIndex(where: { $ 0 > 25 })) //7 |
展望Swift 5.0
附录参考
作者:ShmilyCoder
链接:https://www.jianshu.com/p/86ca289a6e47