Open3
【Swift】Alamofireを触ってみる(async/awaitで書く)
概要
- APIクライアントを作りたい。Alamofireを触ってみる。
- Swiftのasync/awaitを用いて書きたい。
参考
作るもの
- "swift"が入るリポジトリをGitHubのAPIで検索
https://api.github.com/search/repositories?q=swift - ボタンを押したらAPIにアクセスし、結果のjsonをそのままstringでベタ書きする
スクリーンショット
- "RequestAPI"ボタンを押すと1秒くらいで結果が表示される
実装
async/awaitを利用して書く
- (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のときと同じです。