Combine 실습 4

yongbeom kwak·2022년 7월 25일
0

Combine

목록 보기
5/5

이번 실습은 조금 더 복잡한 모델을 이용해보자.

Model


import Foundation

struct RandomUser: Codable, Identifiable,CustomStringConvertible {
    var id = UUID()
    var name: Name
    var photo: Photo
    private enum CodingKeys: String, CodingKey {
        case name = "name"
        case photo = "picture"
    }
    
    static func getDummy() -> Self {
        print(#fileID, #function, #line, "")
        return RandomUser(name: Name.getDummy(), photo: Photo.getDummy())
    }
    
    var profileImgUrl: URL {
        get {
            URL(string: photo.medium)!
        }
    }
    
    var description:String {
        return name.description
    }
}


struct Name: Codable, CustomStringConvertible {
    var title: String
    var first: String
    var last: String
    
    var description: String {
        return "[\(title) \(last), \(first)]"
    }
    
    static func getDummy() -> Self {
        return Name(title: "유튜버", first: "정대리", last: "개발하는")
    }
}

struct Photo: Codable {
    var large : String
    var medium : String
    var thumbnail :String
    
    static func getDummy() -> Self{
        return Photo(large: "https://randomuser.me/api/portraits/women/54.jpg", medium: "https://randomuser.me/api/portraits/women/54.jpg", thumbnail: "https://randomuser.me/api/portraits/women/54.jpg")
    }
}

struct Info : Codable {
    var seed : String
    var resultsCount : Int
    var page : Int
    var version : String
    
    private enum CodingKeys: String, CodingKey {
        case seed = "seed"
        case resultsCount = "results"
        case page = "page"
        case version = "version"
    }
}

struct RandomUserResponse: Codable, CustomStringConvertible {
    var results: [RandomUser]
    var info: Info
    
    private enum CodingKeys: String, CodingKey {
        case results, info
    }
    
    var description: String {
        return "results.count: \(results.count) / info: \(info.seed  )"
    }
    
}

viewModel

import Foundation
import Combine
import Alamofire
import SwiftUI

class RandomUserViewModel: ObservableObject {
    
    var subscription = Set<AnyCancellable>()
    
    @Published var randomusers = [RandomUser] ()
    
    
    var baseUrl = "https://randomuser.me/api/?results=100"
    
    init()
    {
        print(#fileID,#function, #line, "")
        fetchRandomUsers()
    }
    
    func fetchRandomUsers()
    {
        print(#fileID,#function,#line, "")
              
              AF.request(baseUrl)
            .publishDecodable(type: RandomUserResponse.self)
            .compactMap{$0.value} // Value로 옵셔널을 Unwrapping
            .map{$0.results} //results만 가져옴
            .sink {completion in
               
                switch completion{
                case .finished:
                    print("데이터 스트림 완료")
                
                case.failure(let err):
                    print("Error : \(err)")
                }
            } receiveValue: {  [weak self] (receivedValue: [RandomUser]) in
                guard let self = self else {return}
                print("받은 값: \(receivedValue.count)")
                self.randomusers = receivedValue
            }.store(in: &subscription)

    }
    
}

View

import SwiftUI

struct ContentView: View {
    
    @ObservedObject var randomuserViewModel = RandomUserViewModel()
    
    var body: some View {
        
        
        VStack {
            Button {
                randomuserViewModel.randomusers = [RandomUser] ()
            } label: {
                Text("Hello")
            }
            List(randomuserViewModel.randomusers){ aRandomUser in
                RandomUserRowView(aRandomUser)
            }
        }
        
        
    }
}

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

결과

정리

compactMap

  • 내려오는 데이터의 타입 캐스팅 또는 옵셔널 Unwrapping에 사용

print(#fileID,#function, #line, "")
해당 출력문을 이용하여 디버깅에 효율적으로 이용할 수 있다.

profile
IOS개발 공부생

0개의 댓글