Skip to main content

SwiftUI专辑078-completionBlock转化为async/await

· 预计阅读2分钟

headerimg 如果你有一些老的代码使用completion block的方式处理异步,我们可以将其改为使用async/await的方式。

Getting ready

首先创建一个新项目:PaletteGenerator

我们将https://github.com/gscalzo/Lorikeet三方库,以源码的方式集成。

在Utils.swift中加入import UIKit,处理编译错误。

How to do it…

  1. 创建一个List,显示Color
extension Color: Identifiable {
public var id: String {
self.description
}
}
@available(iOS 15.0, *)
struct ContentView: View {
@State var colors: [Color] = []
var body: some View {
ScrollView {
LazyVStack(spacing: 0) {
ForEach(colors){ color in
Rectangle()
.foregroundColor(color)
.frame(height: 100)
}
}
}.edgesIgnoringSafeArea(.vertical)
}
}
  1. 加入extension
extension Color {
var lkt: Lorikeet {
UIColor(self).lkt
}
}

extension Lorikeet {
func generateColorScheme(numberOfColors: Int, withRange range: HSVRange? = nil, using algorithm: Algorithm = .cie2000) async -> [Color] {
await withCheckedContinuation({ continuation in
generateColorScheme(numberOfColors: numberOfColors, withRange: range, using: algorithm) { colors in
continuation.resume(returning: colors.map{ Color($0) })
}
})
}
}
  1. 生成colors
struct ContentView: View {
@State var colors: [Color] = []
var body: some View {
ScrollView {
LazyVStack(spacing: 0) {
ForEach(colors){ color in
Rectangle()
.foregroundColor(color)
.frame(height: 100)
}
}
}
.edgesIgnoringSafeArea(.vertical)
.task {
colors = await Color.blue.lkt.generateColorScheme(numberOfColors: 10)
}
}
}

image-20220117144110684

How it works…

原始的generateColorScheme是通过completion block,调用成功回调。

我们通过withCheckedContinuation函数,将其转化为async/await函数。

如果我们的函数同时还有error, 比如:

func oldAPI(completion: (Result<[UIColor], Error>) -> Void)

此时我们可以使用withCheckedThrowingContinuation函数:

func newAPI() async throws -> [UIColor] {
try await withCheckedThrowingContinuation { continuation in
oldAPI { result in
switch result {
case .success(let value):
continuation.resume(returning: value)
case .failure(let error):
continuation.resume(throwing: error)
}
}
}
}