【iOS印象】Swift 4.1 新特性

2,977 阅读2分钟

语言特性提升
  • 条件一致性(Conditional Conformance
    • Equatable Containers:当可选型、数组、字典等集合与容器类型中的元素遵循 Equatable 或 Hashable 协议,则其同样遵循这些协议。包括 Codable 协议。
    • 自定义容器或集合同样可应用泛型配置支持该特性
// Swfit 4.0

// [String] to [Int?]
let a = ["1","2","x"].map(Int.init)
a == [1,2,nil]    // 期待值应该是 ‘true’,但是~!
编译器报错:
//Binary operator ‘==’ cannot be applied to two ‘[Int?]’ operands.
--------------------------------------
// Swift 4.1 新增特性默认实现
extension Array: Equatable where Element: Equatable { 
    // implementation of == for Array
}

extension Optional: Equatable where Wrapped: Equatable {
    // implementation of == for Optional
}
a == [1,2,nil]                  // true
a.contains(nil)                 // true
[[1,2],[3,4],[]].index(of: [])  // 2
  • JSON Coder 支持驼峰命名与下划线命名转换
    • .keyEncodingStrategy
    • .keyDecodingStrategy
  • Equatable 和 Hashable 的一致性:
    • 对所有属性都遵循 Equatable 或 Hashable 的 struct 和 enum 默认遵循该协议。
    • 注意!class 类型不支持这个特性
    • Comparable 协议?继续按业务逻辑自行实现吧。
  • 协议中的关联类型支持递归约束
protocol Phone {
    associatedtype Version
    associatedtype SmartPhone: Phone where SmartPhone.Version == Version, SmartPhone.SmartPhone == SmartPhone
}
  • 协议中使用 weak 与 unowned 修饰属性将收到编译警告(因为在协议中修饰其没有意义)
class Key {}
class Pitch {}
protocol Tune {
    unowned var key: Key { get set }
    weak var pitch: Pitch? { get set }
}
class Instrument: Tune {
    var key: Key
    var pitch: Pitch?
    init(key: Key, pitch: Pitch?) {
        self.key = key        
        self.pitch = pitch
    }
}
  • typeOfCollection(_:) 方法中,IndexDistance 改为 Int
  • flatMap(_:) 重命名为 compactMap(_:)
平台配置与编译参数更新
  • 编译时导入(Build Imports)
// Swift 4.0#
if os(iOS) || os(tvOS)
    import UIKit
    print("UIKit is available on this platform.")
#else    
    print("UIKit is not available on this platform.")
#endif

// Swift 4.1
#if canImport(UIKit)
    print("UIKit is available if this is printed!")
#endif
  • 编译时判断目标环境(Target Environments)
// Swift 4.0
#if (arch(i386) || arch(x86_64)) && (os(iOS) || os(tvOS) || os(watchOS))
    print("Testing in the simulator.")
#else    
    print("Testing on the device.")
#endif

// Swift 4.1
#if targetEnvironment(simulator)
    print("Testing in the simulator.")
#endif