서버로부터 받은 JSon을 가져온 데이터와 Combine을 사용하여 구독한다
UrlSession 작업을 Alamofire로 변경해본다.
enum API{
case fetchTodos
case fetchPosts
var url: URL{
switch self {
case .fetchPosts: return URL(string: "https://jsonplaceholder.typicode.com/posts")!
case .fetchTodos: return URL(string: "https://jsonplaceholder.typicode.com/todos")!
}
}
}
enum ApiService {
/// Todos 가져오기
/// - Returns: AnyPublisher<[Todo], Error>
static func fetchTodos() -> AnyPublisher<[Todo], Error> {
return URLSession.shared.dataTaskPublisher(for: API.fetchTodos.url)
.map{$0.data}
.decode(type: [Todo].self, decoder: JSONDecoder())
.eraseToAnyPublisher()
}
}
import Foundation
import Combine
class ViewModel: ObservableObject {
var subscriptions = Set<AnyCancellable>()
func fetchTodos(){
ApiService.fetchTodos()
.sink { completion in
switch completion {
case .failure(let err):
print("\(err)")
case .finished:
print("Finish")
}
} receiveValue: { (todos: [Todo]) in
print("todos count \(todos.count)")
}.store(in: &subscriptions)
}
}
import SwiftUI
import CoreData
struct ContentView: View {
@StateObject var viewModel:ViewModel
init(){
self._viewModel = StateObject.init(wrappedValue: ViewModel())
//StateObject는 _(언더바)를 붙혀서 초기화를 해줘야함, bind과 같음
}
var body: some View {
VStack{
Button {
self.viewModel.fetchTodos()
} label: {
Text("Todos 호출").foregroundColor(.white)
}
.padding()
.background(RoundedRectangle(cornerRadius: 10).fill(.gray))
}
import Foundation
import Combine
import Alamofire
enum ApiService {
/// Todos 가져오기
/// - Returns: AnyPublisher<[Todo], Error>
static func fetchTodos() -> AnyPublisher<[Todo], Error> {
//AF로 Refactor
return AF.request(API.fetchTodos.url)
.publishDecodable(type: [Todo].self) //디코딩
.value() // 값만 가져오기
.mapError { (afError:AFError) in
//.value를 거치면 AnyPublisher<Value, AFError> 상태이므로 AFError -> Error로 캐스팅
return afError as Error
}
.eraseToAnyPublisher()
}
}
Alamofire는 swift를 기반으로 한 HTTP 네트워킹 라이브러리이다. 이는 공통적인 네트워크 작업을 함에 있어 매우 우아한 인터페이스를 제공한다.