Closed3

SwiftUIの.taskでリロード処理を実装した我

ほへとほへと

これを見る。
https://fatbobman.com/en/posts/mastering_swiftui_task_modifier/


.taskにidを指定して、idが別の値に変更された際にTaskをキャンセル且つ、再作成してくれるらしい。

struct TaskDemo2: View {
    @State var status: Status = .loading
    @State var reloadTrigger = false
    let url = URL(string: "https://source.unsplash.com/400x300")! // get random image url
    var body: some View {
        VStack {
            Group {
                switch status {
                case .loading:
                    Rectangle()
                        .fill(.secondary)
                        .overlay(Text("Loading"))
                case .image(let image):
                    image
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                case .error:
                    Rectangle()
                        .fill(.secondary)
                        .overlay(Text("Failed to load image"))
                }
            }
            .padding()
            .frame(width: 400, height: 300)

            Button(status.loading ? "Loading" : "Reload") {
                reloadTrigger.toggle()  // load image
            }
            .disabled(status.loading)
            .buttonStyle(.bordered)
        }
        .animation(.easeInOut, value: status)
        .task(id: reloadTrigger) { 
            do {
                status = .loading
                var bytes = [UInt8]()
                for try await byte in url.resourceBytes {
                    bytes.append(byte)
                }
                if let uiImage = UIImage(data: Data(bytes)) {
                    let image = Image(uiImage: uiImage)
                    status = .image(image)
                } else {
                    status = .error
                }
            } catch {
                status = .error
            }
        }
    }

    enum Status: Equatable {
        case loading
        case image(Image)
        case error

        var loading: Bool {
            switch self {
            case .loading:
                return true
            default:
                return false
            }
        }
    }
}

idはEquatableを継承して、比較できる状態であることが必須。
https://developer.apple.com/documentation/swiftui/view/task(id:priority:_:)

ほへとほへと

このidをモデル側で保持して、その値を親側で変更できるようにした!

このスクラップは2024/06/25にクローズされました