👋

Swift Task(Async/Await)のCancelの仕方

2021/12/07に公開

Cancel

Swift 5.5で導入されたAsync/AwaitCancelをする方法を簡単に紹介していきます。

Startボタンと、CancelボタンをSwiftUIで実装しています。

前提知識

SwiftUI少し
Async/Await

実装例

import SwiftUI

struct ContentView: View {
    @State var message: String = "Hello"
    @State var downloadTask: Task<(), Never>?
    @State var htmlString: String = ""
    let url: URL = URL(string: "https://api.isevenapi.xyz/api/iseven/6/")!
    
    func download(from urlString: String) async throws -> Data {
        // 重い処理
        let (data, _) = try await URLSession.shared.data(from: url)
        try await Task.sleep(nanoseconds: 3 * 1_000_000_000)
        return data
    }
    
    func start() {
        self.downloadTask = Task {
            self.message = "Downloading Data..."
            
            do {
                let data = try await download(from: urlString)
                self.htmlString = String(data: data, encoding: .utf8)!
                self.message = "Finish!"
            } catch let error {
                if Task.isCancelled {
                    self.message = "Canceled"
                } else {
                    self.message = error.localizedDescription
                }
            }
        }
    }
    
    func cancel() {
        self.downloadTask?.cancel()
    }
    
    var body: some View {
        VStack {
            Text(urlString)
            
            Button("Start") {
                start()
            }
            
            Button("Cancel") {
                cancel()
            }
            
            Text(self.message)
            Text(self.htmlString)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Discussion