idghst.dev
article thumbnail
Published 2023. 3. 17. 09:00
[ Swift ] Network - 실습 Swift
728x90
반응형

Publisher+Utils.swift

import Foundation
import Combine

extension Publisher {

    static func empty() -> AnyPublisher<Output, Failure> {
        return Empty().eraseToAnyPublisher()
    }

    static func just(_ output: Output) -> AnyPublisher<Output, Failure> {
        return Just(output)
            .catch { _ in AnyPublisher<Output, Failure>.empty() }
            .eraseToAnyPublisher()
    }

    static func fail(_ error: Failure) -> AnyPublisher<Output, Failure> {
        return Fail(error: error).eraseToAnyPublisher()
    }
}

 

NetworkService.swift

import Foundation
import Combine

///// Defines the Network service errors.
enum NetworkError: Error {
    case invalidRequest
    case invalidResponse
    case responseError(statusCode: Int)
    case jsonDecodingError(error: Error)
}

final class NetworkService {
    let session: URLSession
    
    init(configuration: URLSessionConfiguration) {
        session = URLSession(configuration: configuration)
    }
    
    func load<T>(_ resource: Resource<T>) -> AnyPublisher<T, Error> {
        guard let request = resource.urlRequest else {
            return .fail(NetworkError.invalidRequest)
        }
        
        return session
            .dataTaskPublisher(for: request)
            .tryMap { result -> Data in
                guard let response = result.response as? HTTPURLResponse,
                      (200..<300).contains(response.statusCode)
                else {
                    let response = result.response as? HTTPURLResponse
                    let statusCode = response?.statusCode ?? -1
                    throw NetworkError.responseError(statusCode: statusCode)
                }
                return result.data
            }
            .decode(type: T.self, decoder: JSONDecoder())
            .eraseToAnyPublisher()
    }
}

 

Resource.swift

import Foundation

struct Resource<T: Decodable> {
    var base: String
    var path: String
    var params: [String: String]
    var header: [String: String]
    
    var urlRequest: URLRequest? {
        var urlComponents = URLComponents(string: base + path)!
        let queryItems = params.map { (key: String, value: String) in
            URLQueryItem(name: key, value: value)
        }
        urlComponents.queryItems = queryItems
        
        var request = URLRequest(url: urlComponents.url!)
        header.forEach { (key: String, value: String) in
            request.addValue(value, forHTTPHeaderField: key)
        }
        
        return request
    }
    
    init(base: String, path: String, params: [String: String] = [:], header: [String: String] = [:]) {
        self.base = base
        self.path = path
        self.params = params
        self.header = header
    }
}

 


 

송수신 Json 형식

Resouce 에서 설정한 URL 의 반환 Json 데이터 목록을 정의 해야합니다

API에 따라 다르기 때문애 확인 후 다르게 작성해줘야 합니다

import Foundation

struct SearchResult: Hashable, Identifiable, Decodable {
    
    var id: Int64
    var login: String
    var avatarUrl: URL
    var htmlUrl: String
    
    enum CodingKeys: String, CodingKey {
        case id
        case login
        case avatarUrl = "avatar_url"
        case htmlUrl = "html_url"
    }
}

 


 

네트워크 선언

let network = NetworkService(configuration: .default)

 

API 호출 리소스 설정

  • base : 기본 주소 작성
  • path : base 주소의 하위 주소 작성
  • params : 파라미터 작성
  • header : Json 데이터 송수신을 위한 Content-Type 등 작성
let resource = Resource<SearchUserResponse>(
    base: "https://api.github.com/",
    path: "search/users",
    params: ["q": keyword],
    header: ["Content-Type": "application/json"])

 

리소스 설정 후 네트워크 로드

❗️ (load) 수신된 데이터에 따라 다르게 작성 해야합니다.

network.load(resource)
    .map { value in value.items }
    .replaceError(with: [])
    .receive(on: RunLoop.main)
    .assign(to: \.users, on: self)
    .store(in: &subscription)
728x90
반응형

'Swift' 카테고리의 다른 글

[ Swift ] Network - 개념  (0) 2023.03.15
[ Swift ] Combine - 실습  (0) 2023.03.13
[ Swift ] Combine - Operator  (0) 2023.03.08
[ Swift ] Combine - Subscriber  (0) 2023.03.06
[ Swift ] Combine - Publisher  (0) 2023.03.03
profile

idghst.dev

@idghst.dev

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!