Open3

【Swift】Alamofireを触ってみる(async/awaitで書く)

だーら(Flamers / Memotia)だーら(Flamers / Memotia)

実装

async/awaitを利用して書く

https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#using-alamofire-with-swift-concurrency

  • (swift初心者でエラーハンドリングとか非同期の書き方は詰められてません..)
APIClient.swift
import Foundation
import Alamofire

class APIClient {

  func fetchData(from url: String) async throws -> String {
    do {
      return try await AF.request(url).serializingString().value
    } catch {
      throw error
    }
  }
}
DataViewModel.swift
import SwiftUI
import Alamofire

class DataViewModel: ObservableObject {
  @Published var dataString: String = ""
  // ↑警告: Publishing changes from background threads is not allowed; make sure to publish values from the main thread (via operators like receive(on:)) on model updates.
  private var apiClient = APIClient()
  private let url = "https://api.github.com/search/repositories?q=swift"

  func requestApi() {
    Task {
      do {
        dataString = try await apiClient.fetchData(from: url)
      } catch {
        throw error
      }
    }
  }
}
ContentView.swift
import SwiftUI

struct ContentView: View {
  @ObservedObject var viewModel = DataViewModel()

  var body: some View {
    VStack {
      Text(viewModel.dataString)
      Button("RequestAPI") {
        viewModel.requestApi()
      }
    }
  }
}

async/awaitを使わない場合はこちら

  • 記事を調べる感じはこちらの方が多く出てきた。
実装
APIClient.swift
import Foundation
import Alamofire

class APIClient {

  func fetchData(from url: String, completion: @escaping (Result<Data, AFError>) -> Void) {
    AF.request(url).responseData { res in
      completion(res.result)
    }
  }
}
DataViewModel.swift
import SwiftUI
import Alamofire

class DataViewModel: ObservableObject {
  @Published var dataString: String = ""
  private var apiClient = APIClient()
  private let url = "https://api.github.com/search/repositories?q=swift"

  func requestApi() {
    apiClient.fetchData(from: url, completion: { [weak self] result in
      DispatchQueue.main.async {
        switch result {
        case .success(let data):
          self?.dataString = String(decoding: data, as: UTF8.self)
        case .failure(let error):
          self?.dataString = "Error: \(error.localizedDescription)"
        }
      }
    })
  }
}
  • ContentViewはasync/awaitのときと同じです。