swift4.2新特性

本文介绍了Swift 4.2的一些重要更新,包括协议的改进,如自动获取所有Case;条件一致性增强,解决了类型推断问题;优化了操作符`&&`和`||`的使用;使安全性提升;新增随机数生成功能,并提供了检查平台条件和编译指令的方法;还更新了数组的相关操作,如`removeAll(where:)`, `allSatisfy()`, `toggle()`, `last(where:)`和`lastIndex(where:)`。" 104477904,510261,嵌入式开发:二进制与十六进制基础,"['嵌入式开发', '二进制', '十六进制', '数值转换']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

swift4.2新特性

CaseInterable协议

在4.2之前我们想打印枚举里面所有的case只能自己通过以下方式去实现:

/// swift4.2之前,错误示例
enum Gait {
    case walk
    case trot
    case canter
    case gallop

    static var allCases: [Gait] = [.walk, .trot, .canter, .gallop]
}

for gait in Gait.allCases {
    print(gait)
}

这样每次新增和删除一个case都要去维护allCases这个数组,这样造成了诸多不便,在Swift 4.2中新增了CaseIterable协议,通过遵循这个协议,会自动生成allCases,例如:

enum Gait: CaseIterable {
    case walk
    case trot
    case canter
    case gallop
    case jog
}

for gait in Gait.allCases {
    print(gait)
}

这样我们就不用去自己维护allCases这个集合了

条件一致性

条件一致性是在Swift 4.1引入的,例如在Swift 4.0的时候下面代码运行会报错:

let animals = ["cat", "dog", "weasel"]
animals.contains("dog") // OK
let coins = [[1, 2], [3, 6], [4, 12]]
/// Error because the element type [Int] is not equatable
coins.contains([3, 6])

然而在Swift 4.1之后类似这种的问题得到了解决:

extension Array: Equatable where Element: Equatable {
    static func ==(lhs: Array<Element>, rhs: Array<Element>) -> Bool {
        let count = lhs.count
        if count != rhs.count { return false } for x in 0..<count {
        if lhs[x] != rhs[x] { return false } }
        return true
    }
}

let coins = [[1, 2], [3, 6], [4, 12]] 
coins.contains([3, 6]) // This now works!

类似的这种一致性有EquatableHashableEncodableDecodable

优化EquatableHashable

例如在Swift 4.1需要实现一下代码的功能需要这样写:

enum Either<Left, Right> {
    case left(Left)
    case right(Right)
}

extension Either: Equatable where Left: Equatable, Right: Equatable {
    static func == (a: Either<Left, Right>, b: Either<Left, Right>) -> Bool {
        switch (a, b) {
        case (.left(let x), .left(let y)):
            return x == y
        case (.right(let x), .right(let y)):
            return x == y
        default:
            return false
        }
    }
}

extension Either: Hashable where Left: Hashable, Right: Hashable {
    var hashValue: Int {
        switch self {
        case .left(let x):
            return x.hashValue
        case .right(let x):
            return x.hashValue
        }
    }
}

var mySet = Set<Either<Int, String>>()

但是在Swift 4.2中不用写以上代码了,帮你默认实现了:

enum Either<Left, Right> {
    case left(Left)
    case right(Right)
}

extension Either: Equatable where Left: Equatable, Right: Equatable { }
extension Either: Hashable where Left: Hashable, Right: Hashable { }

var mySet = Set<Either<Int, String>>()

更加安全的Hashable

Swift 4.1我们遵循Hashable协议时需要这样写:

struct City {
    let name: String
    let state: String
    /// 城市不用比较人口
    let population: Int
}

extension City: Equatable {
    static func ==(a: City, b: City) -> Bool {
        return a.name == b.name && a.state == b.state
    }
}

extension City: Hashable {
    var hashValue: Int {
        return name.hashValue ^ state.hashValue 
    }
}

Swift 4.2引入了一个新的Hasher结构,它提供了一个随机播种的通用散列函数:

struct City {
    let name: String
    let state: String
    /// 城市不用比较人口
    let population: Int
}

extension City: Hashable {
    func hash(into hasher: inout Hasher) {
        name.hash(into: &hasher)
        state.hash(into: &hasher)
    }
}

Hasher中的hash合并算法可以有效的平衡hash的质量和性能,还可以低于阻断式服务攻击,它使用了App启动时生成的随机预处理种子,因此在Swift 4.2中每次启动App时的hash值不一样了,会导致之前一些有序字典或者集合变的无序,当然我们也可以添加环境变量( SWIFT_DETERMINISTIC_HASHING=1)来关掉这个功能

随机数生成

之前的随机数用法:

#if os(iOS) || os(tvOS) || os(watchOS) || os(macOS)
    return Int(arc4random()) 
#else
    return random() // or Int(rand())
#endif

// Return random number in the range 1...6 
func diceRoll() -> Int {
    return 1 + (arc4random() % 6)
}

Swift 4.2中:

let randomIntFrom0To10 = Int.random(in: 0 ..< 10)
let randomFloat = Float.random(in: 0 ..< 1)
let greetings = ["hey", "hi", "hello", "hola"]
print(greetings.randomElement()!)

let randomlyOrderedGreetings = greetings.shuffled()
print(randomlyOrderedGreetings)

还可以自定义随机生成器,遵循RandomNumberGenerator,具体用法在这里就不详细阐述了

检查平台条件

在之前检测平台时,代码如下:


#if os(iOS) || os(watchOS) || os(tvOS)
    import UIKit
    ...
#else
    import AppKit
    ...
#endif

Swift 4.2中:

 #if canImport(UIKit)
    import UIKit
    ...
 #else
     import AppKit
     ...
 #endif

检测是否是模拟器:

#if hasTargetEnvironment(simulator)
    ...
#else
    #warning("We need to test this better")
    ...
#endif

#warning#error编译指令

#warning("这是一个警告")
#error("这是一个错误")

removeAll(where:)

/// removeAll(where:)
var pythons = ["John", "Michael", "Graham", "Terry", "Eric", "Terry"]
pythons.removeAll { $0.hasPrefix("Terry") }
print(pythons)

/// filter
var python2 = ["John", "Michael", "Graham", "Terry", "Eric", "Terry"]
python2 = python2.filter { !$0.hasPrefix("Terry") }
print(python2)

allSatisfy()

//判断数组的所有元素是否全部大于85
let scores = [86, 88, 95, 92]
//返回一个BOOL
let passed = scores.allSatisfy({ $0 > 85 })
print(passed)

//输出: true

toggle()

var isSwift = true
//toggle函数没有返回值
isSwift.toggle()
print(isSwift)

last(where:)lastIndex(where:)

//获取满足条件的数组中的第一个值
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

//在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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值