357 Views
December 17, 22
スライド概要
エンジニアと人生コミュニティで発表したスター乞食になっております
SwiftUI x Concurrency をよ り簡単に bannzai \(^o^)/
みなさん
こう思ったことはないだろうか
async/await 便利
一方、こう思ったことはないだろうか
もっと楽したいぴょん
ここで普段書くようなコードを見てみよう
struct UserView: View { @State var user: User? @State var error: Error? var body: some View { Group { if let user { Text(user.name) } else if let error { ErrorPage(error: error) } else { ProgressView() } } .task { await fetch() } } private func fetch() async { do { user = try await apiClient.fetch(path: "user") } catch { self.error = error } } }
struct UserView2: View { @StateObject var viewModel = UserViewModel() var body: some View { Group { if let user = viewModel.user { Text(user.name) } else if let error = viewModel.error { ErrorPage(error: error) } else { ProgressView() } } .onAppear { viewModel.fetch() } } } final class UserViewModel: ObservableObject { @Published var user: User? @Published var error: Error? func fetch() { Task { @MainActor in do { user = try await apiClient.fetch(path: "user") } catch { self.error = error } } } }
同じパターンだぴょん
パターン 1. Viewの宣言に必要な状態は、値が無ければ読み込み中, 値が存在すればメインコンテンツの表示、エラーならエ ラーの表示 2. .onAppear(もしくは.task)で値を引っ張ってくる
課題 - 同じようなコードを書く。do{}catch{}とかも - 同じようなコードに保ちたい。if let は書き忘れがありそう
赤枠の部分が書き忘れ発生しそうなので 書き忘れが無いように制約をつけたい struct UserView: View { @State var user: User? @State var error: Error? var body: some View { Group { if let user { Text(user.name) } else if let error { ErrorPage(error: error) } else { ProgressView() } } .task { await fetch() } } private func fetch() async { do { user = try await apiClient.fetch(path: "user") } catch { self.error = error } } }
作るぴょん
できた
スターください
Async https://github.com/bannzai/Async
みなさんがスターをくれるまで待ちます Async https://github.com/bannzai/Async
struct UserView3: View {
@Async<User> var async
var body: some View {
switch async(fetch).state {
case .success(let user):
Text(user.name)
case .failure(let error):
ErrorPage(error: error)
case .loading:
ProgressView()
}
}
private func fetch() async throws -> User {
try await apiClient.fetch(path: "user")
}
}
struct UserView4: View {
var body: some View {
AsyncView(fetch, when: (
success: { user in
Text(user.name)
},
failure: { error in
ErrorPage(error: error)
},
loading: {
ProgressView()
}
))
}
private func fetch() async throws -> User {
try await apiClient.fetch(path: "user")
}
}
最高だぴょん
スターください
おしまい \(^o^)/