본문 바로가기
프로그램 개발해서 돈벌기/iOS

[SwiftUI] Http 통신을 MVVM 패턴 예제로 이해하기

by ubmuhan 2022. 10. 31.
반응형

애플리케이션을 생성할 때 일반적으로 API에서 일부 데이터를 가져오기 위해 HTTP 요청을 해야 합니다. 이를 위해 SwiftUI에서 패키지 관리자(Swift-Request 또는 Alamofire와 같은)를 사용할 수 있지만 자체 HTTP 요청 함수를 만드는 것은 매우 쉽습니다. 어떻게 하는지 봅시다. 이 자습서에서는 무료 REST API인 JSONPlaceholder를 사용합니다. 10명의 사용자 목록을 가져와서 보기에 표시하기 위해 /users 엔드포인트를 호출합니다.

 

안녕하세요. 오늘은 http 통신을 알아 보려고 합니다. 위 설명은 개략적인 소개 내용입니다. 설명은 주석으로 소스에 설명을 넣겠습니다.

MVVM 패턴을 잘 사용한 샘플입니다.

 

// ~App.swift

import SwiftUI

@main
struct moneyballcodeApp: App {

    // Network (ObservableObject) 변수 할당
    var network = Network()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
            
            // 뷰가 데이터를 공유할때 이용
            .environmentObject(network)
        }
    }
}

 

// ContentView.swift

import SwiftUI

struct ContentView: View {
    @EnvironmentObject var network: Network

    var body: some View {
        ScrollView {
            Text("All users")
                .font(.title)
                .bold()

            VStack(alignment: .leading) {
            
                // network.users를 반복하여 ID, 이름, 이메일, 전화를 표시함
                ForEach(network.users) { user in
                    HStack(alignment:.top) {
                        Text("\(user.id)")

                        VStack(alignment: .leading) {
                            Text(user.name)
                                .bold()

                            Text(user.email.lowercased())

                            Text(user.phone)
                        }
                    }
                    .frame(width: 300, alignment: .leading)
                    .padding()
                    .background(Color(#colorLiteral(red: 0.6667672396, green: 0.7527905703, blue: 1, alpha: 0.2662717301)))
                    .cornerRadius(20)
                }
            }

        }
        .padding(.vertical)
        
        // ContentView가 생성될때 getUsers를 호출함.
        .onAppear {
            network.getUsers()
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .environmentObject(Network())
    }
}

 

// network.swift

import SwiftUI

class Network: ObservableObject {
    @Published var users: [User] = []

    func getUsers() {
        guard let url = URL(string: "https://jsonplaceholder.typicode.com/users") else { fatalError("Missing URL") }

        let urlRequest = URLRequest(url: url)

        let dataTask = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
            if let error = error {
                print("Request error: ", error)
                return
            }

            guard let response = response as? HTTPURLResponse else { return }

            if response.statusCode == 200 {
                guard let data = data else { return }
                DispatchQueue.main.async {
                    do {
                        let decodedUsers = try JSONDecoder().decode([User].self, from: data)
                        
                        // Users 배열로 디코딩
                        self.users = decodedUsers
                    } catch let error {
                        print("Error decoding: ", error)
                    }
                }
            }
        }
        dataTask.resume()
    }
}

 

// user.swift
// JSON 파일 형식에 맞게 사용자 구조체를 만듭니다.
import Foundation

// Identifiable : JSON 자료 내 아이템은 유니크하다는 뜻 입니다.
// Decodable : JSON 자료를 User 데이터 모델로 변환할 수 있다는 뜻 입니다.
struct User: Identifiable, Decodable {
    var id: Int
    var name: String
    var username: String
    var email: String
    var address: Address
    var phone: String
    var website: String
    var company: Company

    struct Address: Decodable {
        var street: String
        var suite: String
        var city: String
        var zipcode: String
        var geo: Geo

        struct Geo: Decodable {
            var lat: String
            var lng: String
        }
    }

    struct Company: Decodable {
        var name: String
        var catchPhrase: String
        var bs: String
    }
}

 

 

  • user.swift  ==  Model
  • contentView.swift  ==  View
  • network.swift ==  View Model

 

* 위 샘플은 xcode 14.01에서 테스트한 코드입니다. (swift 5)

 

<< 참조 >>

https://designcode.io/swiftui-advanced-handbook-http-request

 

SwiftUI Advanced Handbook - Design+Code

An extensive series of tutorials covering advanced topics related to SwiftUI, with a main focus on backend and logic to take your SwiftUI skills to the next level

designcode.io

 

- 유저 Json 데이타

https://jsonplaceholder.typicode.com/users

 
 
 
 
반응형

댓글