使用Swift开发,你应该知道的好习惯(三)

198 阅读2分钟

好习惯一

好习惯二

借鉴# Swift Algorithms的5个好用方法

www.swiftwithvincent.com/blog/5-very…

import Algorithms

let names = ["David", "Kyle", "Karoy", "Nate"]
// 使用chunks对集合进行分块,ofCount参数指定每一块的最大长度
let evenly = names.chunks(ofCount: 2)
// equivalent to [["David", "Kyle"], ["Karoy", "Nate"]]

let numbers = [10, 20, 30, 10, 40, 40, 10, 20]
// 使用chunked对集合进行按条件分块
let chunks = numbers.chunked(by: { $0 <= $1 })
// [[10, 20, 30], [10, 40, 40], [10, 20]]

// 使用eventlyChunked进行平均分块
let evenChunks = (0..<15).evenlyChunked(in: 3)
// equivalent to [0..<5, 5..<10, 10..<15]


var source = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
// 使用randomSample进行随机取样
let sample = source.randomSample(count: 4)
// e.g. [30, 10, 70, 50]


let numbers = [10, 20, 30, 40, 50]
var matchingIndices: Set<Int> = []
// 使用indexed返回由元组组成的迭代器,其中元素第一个参数是真正的下标,第二个参数是对应的值
for (i, n) in numbers.indexed() {
    if n.isMultiple(of: 20) {
        matchingIndices.insert(i)
    }
}
// matchingIndices == [1, 3]

let numbers = [7, 1, 6, 2, 8, 3, 9]
// 使用min获取最小的n个数
let smallestThree = numbers.min(count: 3, sortedBy: <)
// [1, 2, 3]

// 使用max获取最大的n个数
let biggestThree = numbers.max(count: 3, sortedBy: <)
// [7, 8, 9]

// .compacted(), .firstNonNil() & .uniqued()

let array: [Int?] = [10, nil, 30, nil, 2, 3, nil, 5]
// compacted和compactMap类似,只不过compactMap可以指定返回的类型。而compacted返回原有类型的非空值
let withNoNils = array.compacted()
// Array(withNoNils) == [10, 30, 2, 3, 5]

let strings = ["three", "3.14", "-5", "2"]
// 获取首个非空值的下标
if let firstInt = strings.firstNonNil({ Int($0) }) {
    print(firstInt)
    // -5
}

let numbers = [1, 2, 3, 3, 2, 3, 3, 2, 2, 2, 1]
// 进行去除重复值。和构造一个Set一样
let unique = numbers.uniqued()
// Array(unique) == [1, 2, 3]

使用@Entry宏简化 EnvironmentKey、PreferenceKey等等的定义

swiftwithmajid.com/2024/07/09/…

没有@Entry宏之前,我们要定义EnvironmentKey、PreferenceKey的代码如下

public enum UserState {
    public init(hasActiveSubscription: Bool, isEligibleForIntroOffer: Bool) {
        if hasActiveSubscription {
            self = .pro
        } else if isEligibleForIntroOffer {
            self = .new
        } else {
            self = .churned
        }
    }
    
    case new
    case pro
    case churned
}
// 定义符合 EnvironmentKey协议 的 UserStateEnvironmentKey类型。 
struct UserStateEnvironmentKey: EnvironmentKey {
    static var defaultValue: UserState = .new
}

// EnvironmentValues 类型添加扩展,提供对UserStateEnvironmentKey类型实例的访问
extension EnvironmentValues {
    public var userState: UserState {
        get { self[UserStateEnvironmentKey.self] }
        set { self[UserStateEnvironmentKey.self] = newValue }
    }
}

有了Entry宏之后,代码简化了非常多。 使用Entry宏还可以定义 environment, transactions, container, and focused 等

extension EnvironmentValues {
    // 使用 Entry宏,只需要定义默认值,符合EnvironmentKey协议的类型,Entry宏会自动帮我们实现
    @Entry var userState = UserState.new
}

@main
struct MyApp: App {
    @State var userState = UserState.new
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(.userState, userState)
        }
    }
}