이번 실습은 조금 더 복잡한 모델을 이용해보자.
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 )"
}
}
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)
}
}
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, "")
해당 출력문을 이용하여 디버깅에 효율적으로 이용할 수 있다.