반응형
버스 위치 정보 어플을 만들면서 RxSwift를 사용해서 API 호출을 하는 코드 예시입니다.
reponseDecodable을 통해서 바로 데이터를 변환해서 적용했습니다.
static func getRequest(url: String, param: [String: Any]) -> Observable<Result<BusRouteModel, Error>> {
let header: HTTPHeaders = [
"Content-Type": "application/json"
]
return Observable.create { observer -> Disposable in
AF.request(url, method: .get, parameters: param, encoding: URLEncoding.default, headers: header)
.responseDecodable(of: BusRouteModel.self) { response in
switch response.result {
case .success(let data):
observer.onNext(.success(data))
case .failure(let error):
observer.onError(error)
}
}
return Disposables.create()
}
}
BusRouteModel
struct BusRouteModel: Codable {
let comMsgHeader: COMMsgHeader
let msgHeader: MsgHeader
let msgBody: MsgBody
}
// MARK: - COMMsgHeader
struct COMMsgHeader: Codable {
let responseMsgID, responseTime, requestMsgID, successYN: JSONNull?
let returnCode, errMsg: JSONNull?
}
// MARK: - MsgBody
struct MsgBody: Codable {
let itemList: [ItemList]
}
// MARK: - ItemList
struct ItemList: Codable {
let busRouteID, busRouteNm, busRouteAbrv, length: String
let routeType, stStationNm, edStationNm, term: String
let lastBusYn, lastBusTm, firstBusTm, lastLowTm: String
let firstLowTm, corpNm: String
enum CodingKeys: String, CodingKey {
case busRouteID = "busRouteId"
case busRouteNm, busRouteAbrv, length, routeType, stStationNm, edStationNm, term, lastBusYn, lastBusTm, firstBusTm, lastLowTm, firstLowTm, corpNm
}
}
// MARK: - MsgHeader
struct MsgHeader: Codable {
let headerMsg, headerCD: String
let itemCount: Int
enum CodingKeys: String, CodingKey {
case headerMsg
case headerCD = "headerCd"
case itemCount
}
}
// MARK: - Encode/decode helpers
class JSONNull: Codable, Hashable {
public static func == (lhs: JSONNull, rhs: JSONNull) -> Bool {
return true
}
public var hashValue: Int {
return 0
}
public init() {}
public required init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if !container.decodeNil() {
throw DecodingError.typeMismatch(JSONNull.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for JSONNull"))
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encodeNil()
}
}
Observable: subscribe 전까지 아무일도 일어나지 않음
-> 구독 후 이벤트가 발생하고 complete 또는 error 이벤트가 발생하기 전까지 next 이벤트가 발생함
create: observer들에게 어떤 event가 발생하는지 알려줌
->
disposable: 각종 Disposable을 반환하는 create 메소드를 가진 구조체
-> 리소스를 해제하고 이벤트 구독을 중지함
Observable.create: 인자로 escaping closure를 받음
Disposables.create에 클로저를 하나 전달하면AnonymousDisposable 인스턴스가 만들어진다. 이 인스턴스의 dispose는 생성될 때 등록해둔 클로저를 실행한다.
제네릭 타입을 사용한 예시
import Foundation
import RxSwift
import RxCocoa
import Alamofire
class NetworkManager {
static let shared = NetworkManager()
func getCommonHeaders() -> HTTPHeaders {
let headers: HTTPHeaders = [
"Content-Type":"application/json",
]
return headers
}
func getRequest<T:Decodable>(url: String,
param: [String: Any]?,
responseModel: T.Type) -> Observable<Result<T, Error>> {
let header: HTTPHeaders = [
"Content-Type": "application/json"
]
return Observable.create { observer -> Disposable in
AF.request(url, method: .get, parameters: param, encoding: JSONEncoding.default, headers: header)
.responseDecodable(of: responseModel.self) { response in
switch response.result {
case .success(let data):
observer.onNext(.success(data))
case .failure(let error):
observer.onError(error)
}
}
return Disposables.create()
}
}
}
반응형
'Swift' 카테고리의 다른 글
notRunnging 상태에서 링크 및 푸시에서 접근시 (0) | 2023.01.17 |
---|---|
Alamofire Swift (0) | 2022.07.15 |
iOS ScrollView 설정 (0) | 2022.06.05 |
iOS RxSwift GPS (0) | 2022.05.12 |
iOS 분리된 타겟 내부 XML 파일 파싱 (0) | 2022.05.02 |