SwiftUI で 外部API を叩く

本記事は下記を参考にしています。

qiita.com


モチベーション

  • 昨日作った API を SwiftUI から利用したい
  • SwiftUI で 外部API を叩いた経験が無いのでやりたい

開発環境

> xcodebuild -version
Xcode 13.1
Build version 13A1030d

つくったもの

f:id:tokizuoh:20220416151551p:plain

コード

モデル

import Foundation

struct Word: Decodable, Identifiable {
    var id = UUID()

    var japaneseWord: String
    var romanAlphabet: String
    var vowels: String

    enum CodingKeys: String, CodingKey {
        case japaneseWord = "japanese_word"
        case romanAlphabet = "roman_alphabet"
        case vowels = "vowels"
    }
}

ContentView

import SwiftUI

struct ContentView: View {
    @ObservedObject var fetcher = WordFetcher()
    
    var body: some View {
        NavigationView {
            List(fetcher.words) { word in
                WordView(word: word)
            }
            .navigationTitle(Text("検索結果"))
        }
    }
}

List に使う View

import SwiftUI

struct WordView: View {
    let word: Word
    
    var body: some View {
        VStack(alignment: .leading) {
            Text(word.japaneseWord)
                .bold()
                .font(.headline)
                .lineLimit(0)
                .padding(Edge.Set.top, 4.0)
            Text(word.romanAlphabet)
                .font(.footnote)
                .lineLimit(1)
                .padding(Edge.Set.bottom, 2.0)
            HStack {
                Spacer()
                Text(word.vowels)
                    .foregroundColor(.gray)
                    .lineLimit(1)
            }
        }
    }
}

Fetcher

import Foundation

final class WordFetcher: ObservableObject {
    private let url = "https://{***}?input_text=aaa"
    
    @Published var words: [Word] = []
    
    init() {
        fetchWords()
    }
    
    private func fetchWords() {
        URLSession.shared.dataTask(with: URL(string: url)!) { data, response, error in
            guard let data = data else {
                return
            }
            let decoder: JSONDecoder = JSONDecoder()
            do {
                let words = try decoder.decode([Word].self, from: data)
                DispatchQueue.main.async {
                    self.words = words
                }
            } catch {
                print("FAILED DECODER:", error.localizedDescription)
            }
        }.resume()
    }
}

参考