Rx Swift 네트워크 요청
RxSwift 에 들 어간 지 오래 되 었 습 니 다.그 전에 프로젝트 에서 RxSwift 를 작은 범위 에서 만 사 용 했 습 니 다.응답 식 프로 그래 밍 을 잘 사용 하기 위해 프로젝트 에서 RxSwift 를 더욱 넓 게 사용 하기 로 결 정 했 습 니 다.그리고 RxSwift 의 네트워크 요청 을 연 구 했 습 니 다.현재 네트워크 요청 과 관련 된 사례 는 대부분 RXSwift(4.0.0)또는 더 빠 른 라 이브 러 리 를 바탕 으로 작 성 된 것 입 니 다.이 글 은 현재 최신 버 전(4.2.0)버 전 을 바탕 으로 쓴 것 으로 Rx Swift 버 전의 업데이트 로 인해 그 안의 문법 사용 에 변화 가 생 겼 고 정리 하 는 과정 에서 문제 가 생 겼 습 니 다.나중에 배 운 친구 들 이 시간 을 절약 할 수 있 도록 기록 하기 로 결 정 했 습 니 다.
네트워크 요청
1.RxSwift 관련 라 이브 러 리 버 전 사용
import Foundation
import Moya
enum APIService{
case mainClassList
}
extension APIService:TargetType{
var baseURL: URL {
return URL(string:"http://cmsadmin.fotoable.net")!
}
var path: String {
switch self {
case .mainClassList:
return "/sandboxColor/category"
}
}
var method: Moya.Method {
switch self {
case .mainClassList:
return .get
}
}
var parameters: [String : Any]? {
switch self {
case .mainClassList:
return nil
}
}
var parameterEncoding: ParameterEncoding {
return URLEncoding.default
}
var sampleData: Data {
return "{}".data(using: String.Encoding.utf8)!
}
var task: Task {
return .requestPlain
}
var headers: [String : String]? {
return nil
}
}
먼저,우 리 는 매 거 진 APIService 를 정 의 했 습 니 다.역할 은 주로 내부 에서 네트워크 요청 의 인 터 페 이 스 를 정의 한 다음 에 프로 토 콜 TargetType 을 확장 하 는 것 입 니 다.우 리 는 안의 인 자 를 일일이 해석 합 니 다.3.네트워크 요청 을 하기 전에 네트워크 에서 요청 한 데 이 터 를 JSON 을 통 해 Model 로 전환 하 는 준 비 를 해 야 합 니 다.여기 서 우 리 는 두 가지 방식 으로 전환(프로젝트 의 상황 에 따라 유연 하 게 선택 하여 사용)했 습 니 다.하 나 는 Object Mapper 라 이브 러 리 를 통 해 전환 되 었 고 하 나 는 HandyJSON 라 이브 러 리 를 통 해 전환 되 었 으 며 각각 Response 류 를 통 해 확장 되 었 습 니 다.다음은 이 두 가지 방식 에 대한 포장 이다.
첫째,Object Mapper 라 이브 러 리 를 사용 하여 JSON 을 Model 로 변환 합 니 다.
import Foundation
import RxSwift
import Moya
import ObjectMapper
// MARK: - Json -> Model
extension Response {
func mapObjectModel<T: BaseMappable>(_ type: T.Type, context: MapContext? = nil) throws -> T {
guard let object = Mapper<T>(context: context).map(JSONObject: try mapJSON()) else {
throw MoyaError.jsonMapping(self)
}
return object
}
func mapObjectArray<T: BaseMappable>(_ type: T.Type, context: MapContext? = nil) throws -> [T] {
guard let array = try mapJSON() as? [[String : Any]] else {
throw MoyaError.jsonMapping(self)
}
return Mapper<T>(context: context).mapArray(JSONArray: array)
}
}
// MARK: - Json -> Observable<Model>
extension ObservableType where E == Response {
// Json Observable<Model>
public func mapObjectModel<T: BaseMappable>(_ type: T.Type) -> Observable<T> {
return flatMap { response -> Observable<T> in
return Observable.just(try response.mapObjectModel(T.self))
}
}
// Json Observable<[Model]>
public func mapObjectArray<T: BaseMappable>(_ type: T.Type) -> Observable<[T]> {
return flatMap { response -> Observable<[T]> in
return Observable.just(try response.mapObjectArray(T.self))
}
}
}
둘 째 는 핸 디 JSON 라 이브 러 리 로 JSON 을 Model 로 변환
import Foundation
import RxSwift
import Moya
import HandyJSON
extension ObservableType where E == Response {
public func mapHandyJsonModel<T: HandyJSON>(_ type: T.Type) -> Observable<T> {
return flatMap { response -> Observable<T> in
return Observable.just(response.mapHandyJsonModel(T.self))
}
}
}
extension Response {
func mapHandyJsonModel<T: HandyJSON>(_ type: T.Type) -> T {
let jsonString = String.init(data: data, encoding: .utf8)
if let modelT = JSONDeserializer<T>.deserializeFrom(json: jsonString) {
return modelT
}
return JSONDeserializer<T>.deserializeFrom(json: "{\"msg\":\" \"}")!
}
}
4.MainClassView Model 에서 봉 인 된 인 터 페 이 스 를 사용 하여 네트워크 요청 을 합 니 다.코드 는 다음 과 같 습 니 다.
import RxSwift
import Moya
import ObjectMapper
import HandyJSON
import RxCocoa
class MainClassViewModel {
private let provider = MoyaProvider<APIService>()
let disposeBag = DisposeBag()
var dataSource = BehaviorRelay<[MainClassModelMapObject_sub]>(value:[])
var networkError = BehaviorRelay(value: Error.self)
}
//MARK: --
extension MainClassViewModel {
// -- ObjectMapper
func getClassListWithMapObject(){
provider.rx.request(.mainClassList).asObservable().mapObjectModel(MainClassModelMapObject.self).subscribe({ [unowned self] (event) in
switch event {
case let .next(classModel):
print("ObjectMapper -- ")
self.dataSource.accept(classModel.data)
case let .error( error):
print("error:", error)
self.networkError.accept(error as! Error.Protocol)
case .completed: break
}
}).disposed(by: self.disposeBag)
}
// -- HandyJSON
func getClassListWithMapHandyJson(){
provider.rx.request(.mainClassList).asObservable().mapHandyJsonModel(MainClassModel.self).subscribe({ [unowned self] (event) in
switch event {
case let .next(classModel):
print("HandyJSON -- ")
case let .error( error):
print("error:", error)
self.networkError.accept(error as! Error.Protocol)
case .completed: break
}
}).disposed(by: self.disposeBag)
}
}
여기 서 두 가지 방식 으로 각각 mainClassList API 인터페이스 에 대해 네트워크 요청 을 했 습 니 다.유일 하 게 다른 것 은 네트워크 에서 데 이 터 를 요청 할 때 하 나 는 mapObject Model 을 사용 하여 JSON 을 Model 로 바 꾸 는 것 입 니 다.하 나 는 mapHandy JSonModel 을 사용 하여 JSON 을 Model 로 바 꾸 는 것 입 니 다.우 리 는 서로 다른 라 이브 러 리 를 사용 하기 때문에 JSON 을 Model 로 바 꾸 었 습 니 다.이 두 가지 실현 방식 은 아직도 약간의 차이 가 있다.다음은 이 두 가지 모델 의 구체 적 인 실현 방식 이다.첫째,프로 토 콜 실현 Mappable
import UIKit
import ObjectMapper
class MainClassModelMapObject: Mappable {
var code:NSInteger?
var data:[MainClassModelMapObject_sub]!
required init?(map: Map) {}
func mapping(map: Map) {
code <- map["code"]
data <- map["data"]
}
}
class MainClassModelMapObject_sub: Mappable {
var ID:String?
var name:String?
var desc:String?
var imgUrl:String?
var gifUrl:String?
var isUpdate:Bool?
var backgroundGroup:NSInteger?
required init?(map: Map) {}
func mapping(map: Map) {
ID <- map["ID"]
name <- map["name"]
desc <- map["desc"]
imgUrl <- map["imgUrl"]
gifUrl <- map["gifUrl"]
isUpdate <- map["isUpdate"]
backgroundGroup <- map["backgroundGroup"]
}
}
둘째,협의 실현 HandyJSON
import UIKit
import HandyJSON
struct MainClassModel: HandyJSON {
var code:NSInteger?
var data:[MainClassModel_sub]!
}
struct MainClassModel_sub: HandyJSON {
var ID:String?
var name:String?
var desc:String?
var imgUrl:String?
var gifUrl:String?
var isUpdate:Bool?
var backgroundGroup:NSInteger?
}
5.이상 은 RxSwift 를 사용 하여 네트워크 요청 을 분석 한 것 입 니 다.다음 에 예 를 들 어 어떻게 사용 하 는 지 보 겠 습 니 다.MainClassView Model 에서 저 희 는 dataSource 를 사용 하여 네트워크 요청 으로 돌아 온 데 이 터 를 저 장 했 습 니 다.저 희 는 ViewController 에서 tableview 로 이 데 이 터 를 보 여 드 리 려 면 데이터 원본 과 TableView 를 미리 연결 해 야 합 니 다.다음은 예제 코드 입 니 다.
//cell
viewModel.dataSource.bind(to: tableView.rx.items) { (tableView, row, element) in
let cell = tableView.dequeueReusableCell(withIdentifier: "MainClassTableViewCell", for: IndexPath(row: row, section: 0)) as! MainClassTableViewCell
cell.setModel(model: element)
// configure cell
return cell
}
.disposed(by: disposeBag)
사용 할 곳 에서 호출 방법 getClassList With MapObject()또는 getClassList With MapHandy JSon()3.총화
이 부분의 내용 은 RxSwift 에 대해 어느 정도 알 고 있 는 파트너 학습 에 적합 합 니 다.글 의 중점 은 RxSwift 네트워크 요청 에 관 한 지식 을 배우 고 이해 하 는 데 도움 을 주 는 것 입 니 다.다음은 demo 입 니 다.
demo
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
swift4로 다른 타입의 observe를 정리해 rxswift로 merge한다오늘은 swift! 버튼을 탭했을 때의 이벤트라든지, UserDefaults의 정보가 갱신된 타이밍이라든지, home로부터 돌아온 타이밍이라든지… 라는 것이 있었으므로, 비망록도 겸해! merge1.swift Any...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.