Using API Data

Published by @SoNiceInfo at 6/24/2020


I'll show you how to use data from an API on a web server.
You can implement this with minimum changes because this page is based on Using Mock Data which conform to MVVM pattern.


We're going to make an app that displays a list of TV programs.
The creation process is as follows
The structure of the folder looks like the one on the right.

The changes from Using Mock Data are second and third.
  • Creating a Model (ProgramModel.swift)
  • Creating a Helper to Load Data from API (APIfetch.swift)
  • Creating a ViewModel and View (ProgramView.swift)

Creating a Model (ProgramModel.swift)

This section is the same as Using Mock Data. Model defines the struct of the data.
structs can be nested.
A TV program has id, name, summary and image (medium size).

//  ProgramModel.swift

import SwiftUI

struct Img: Hashable, Codable {
    var large: String?
    var medium: String?
    var small: String?

struct Program: Hashable, Codable {
    let id: Int
    let name: String
    let summary: String
    let image: Img

Creating API Data (programs.json)

API Data can be fetched as programs.json. (Please use this file for this verification only.)

    {"id": 0, "name": "あるぱか散歩", "summary": "あるぱかさんといっしょに街歩きをしましょう", "image": { "medium": "animal_arupaka"}},
    {"id": 1, "name": "ブタトーク", "summary": "MCぶったさんの独壇場",  "image": { "medium": "animal_buta"}},
    {"id": 2, "name": "とっとこはむはみー", "summary": "はむはみーが大冒険",  "image": { "medium": "animal_hamster"}},
    {"id": 3, "name": "ひよっと", "summary": "ひよっとちゃんがいろんなことに挑戦するよ",  "image": { "medium": "animal_hiyoko"}},
    {"id": 4, "name": "わんさんといっしょ", "summary": "わんさんといっしょに歌ったり踊ったりしよう",  "image": { "medium": "animal_inu"}}

Creating a Helper to Load Data from API (APIfetch.swift)

Create a helper to load the API data into the struct of a model.
I think it can be used for other purposes than this program.
Use URLSession.shared.dataTask to fetch Web data.
Use DispatchQueue.main.async to do async proccess.
You can use this data by passing completion when calling apiFetch.

//  APIfetch.swift

import SwiftUI

func apiFetch<T: Decodable>(_ url: String, completion: @escaping ([T]) -> Void) {
    guard let url = URL(string: url) else { return }

    URLSession.shared.dataTask(with: url) { (data, response, error) in
        guard let data = data else { return }
        let decoder: JSONDecoder = JSONDecoder()
        do {
            let resData = try decoder.decode([T].self, from: data)
            DispatchQueue.main.async {
        } catch {
            fatalError("Couldn't load \(url) :\n\(error)")

Creating a ViewModel and View (ProgramView.swift)

Use the helper in ProgramViewModel to fetch data.
Understanding Property Wrappers also show you how to use ObservableObject. Finally, call ProgramView.swift from ContentView.Swift.

//  ProgramView.swift

import SwiftUI

class ProgramViewModel: ObservableObject {
    // If you use a combination of ScrollView and ForEach in View,
    // The problem is that it is not updated.
    // As a workaround, I've included a blank data in the initial value.
    // Reference ->
    @Published var data: [Program] = [Program(id: 0, name: "", summary: "", image: Img(medium: ""))]

    init() {
        // Call apiFetch this time
        apiFetch(""){ resData in
   = resData

struct ProgramView: View {
    @ObservedObject var programVM = ProgramViewModel()

    var body: some View {
        ScrollView(.vertical, showsIndicators: false) {
            VStack(spacing: 10) {
                // Process the Program in sequence
                ForEach(, id: \.id) { (program) in
                    ZStack(alignment: .bottom) {
                            .frame(width: UIScreen.main.bounds.width, height: 300)
                            .background(LinearGradient(gradient: Gradient(colors: [.yellow, .red, .purple]), startPoint: .bottomLeading, endPoint: .topTrailing))
                            .clipShape(RoundedRectangle(cornerRadius: 20))
                        VStack {

struct ProgramView_Previews: PreviewProvider {
    static var previews: some View {
//  ContentView.swift

import SwiftUI

struct ContentView: View {

    var body: some View {

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
The result of displaying a TV show using API data


Using Mock Data
ios - SwiftUI ForEach not correctly updating in scrollview - Stack Overflow


かわいいフリー素材集 いらすとや

    I released iOS App!

    ToDo App

    Visualize Activity, Data sharing with iCloud, Dark mode supported.


    IP Address bookmark.

    Check and bookamrk IP address of all interfaces with geolocation.