article

Monday, February 28, 2022

SwiftUI MVVM (Model View View Model) design pattern

SwiftUI MVVM (Model View View Model) design pattern with ObservableObject — @Published — @ObservedObject fetch JSON data

ContentView.swift
 
//
//  ContentView.swift
//  SwiftUIProject
//
//  Created by Cairocoders
//

import SwiftUI

struct ContentView: View {
    
   @ObservedObject var viewModel = ContentViewModel()
    
   var body: some View {
      NavigationView {
          VStack {
              List(viewModel.items, id: \.id) { item in
                   VStack(alignment: .leading) {
                      Text(item.title)
                      Text(item.completed.description)
                        .font(.system(size: 11))
                        .foregroundColor(.gray)
                   }
              }
              .listStyle(GroupedListStyle())
              
          }.onAppear(perform: {
             viewModel.fetchData()
          })
        .navigationBarTitle("Fetch JSON Datas")
      }
   }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
ViewModel.swift
 
//
//  ViewModel.swift
//  SwiftUIProject
//
//  Created by Cairocoders
//

import SwiftUI

class ContentViewModel: ObservableObject {
  @Published var items = [Model]()
  func fetchData() {
    let api = "https://jsonplaceholder.typicode.com/todos"
    guard let url = URL(string: api) else { return }
    URLSession.shared.dataTask(with: url) { (data, response, error) in
      do {
         if let data = data {
           let result = try JSONDecoder().decode([Model].self, from: data)
           DispatchQueue.main.async {
              self.items = result
           }
         } else {
           print("No data")
         }
      } catch (let error) {
         print(error.localizedDescription)
      }
     }.resume()
  }
}
Model.swift
 
//
//  Model.swift
//  SwiftUIProject
//
//  Created by Cairocoders
//

import SwiftUI

struct Model: Decodable {
   let id: Int
   let userId: Int
   let title: String
   let completed: Bool
}

Related Post