Network 연결하기
- url 에 필요한 리소스
- URLComponents에 ⬅️ 만들어진 url 리소스 넣기
- URLQueryItems에 넣을 쿼리 파라매터(params) 들 추가하기
- URLRequest 만들기 ⬅️ URLComponents.url 넣기
- header 요소들, forEach 문으로 ➡️ URLRequest에 .addValue하여 넣기
리팩토링 하기 전
let base = "https://api.github.com/"
let path = "user/\(keyword)"
let params: [String:String] = [:]
let header: [String:String] = ["Content-Type": "application/json"]
let urlComponent = URLComponents(string: base + path)
let queryItems = params.maps { (key: String, value: String) in
return URLQueryItems(name: key, value: value)
}
urlComponent.queryItems = queryItems
var request = URLRequest(url: urlComponent.url!)
header.forEach{ (key: String, value: String) in
request.addValue(value, forHTTPHeaderField: key)
}
URLSession.shard
.dataTaskPublisher(for: request)
.tryMap{ (data: Data, response: URLResponse) -> Data in // error처리: tryMap(o)
guard let response = response as? HTTPURLResponse,
(200..<300).contains(response.statusCode) else {
let response = response as? HTTPURLResponse
let statusCode = response.statusCode ?? -1
throw NetworkError.responseError(statusCode: statusCode)
}
return data
.decode(type: UserProfile.self, decode: JSONDecoder())
.receive(on: Runloop.main)
.sink{ completion in
switch completion {
case .failure(let error)
self.user = nil
case .finished: break
}
}.store(in: &subscriptions)
리팩토링 후
- network 연결에 필요한 url resources 들을 만들어서 ➡️ load() 에 넣어준다.
- load() 에서는, urlRequest를 뽑아서, session에 넣고, dataTask 를 만들어 ➡️ publisher 을 return 한다.
- Resource 는 UserProfile 을 받기 위한 resource이니, 타입은 <UserProfile> 이다.
let network = NetworkService(configuration: .default)
// Resource
let resource = Resource<UserProfile>(
base: "https://api.github.com/",
path: "users/\(keyword)",
params: [:],
header: ["Content-Type":"application/json"])
// NetworkService
network.load(resource)
.receive(on: Runloop.main)
.sink{ completion in
switch completion {
case .failure(let error):
self.user = nil
case .finished: break
}
} receiveValue: { user in
self.user = user
}.store(in: &subscrptions)