123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- //
- // APIClient.swift
- //
- import Foundation
- import Alamofire
- import ReactiveCocoa
- import ReactiveSwift
- /**
- 통신 구현 객체
-
- - Parameters:
- - url: String not Optinal 기본주소
- - reqParam: dictionary Optinal 전달 파라메터
- - headerParam: dictionary Optinal 헤더 파라메터
- - fileParam: dictionary Optinal 파일 파라메터
- - progressShow: Bool 프로그래스바의 표현여부
- - entype: ENCTYPE 인코딩타입, default 기본 json option
- - ENCTYPE: alamofire의 인코딩 타입을 감추는 래퍼
- - callBack: async 호출일 경우 외부 클로저와 브릿징해준다
-
- */
- class APIClient: NSObject {
- private var url:String!
- private var reqParam:[String:Any]?
- private var headerParam:[String:String]?
- private var fileParam:[[String:Data]]?
- private var progressShow:Bool = true
- private var entype:ENCTYPE = .default
- private var returnType:ENCTYPE = .json
- enum ENCTYPE{
- case `default`
- case json
-
- func getParameterEncoding() -> ParameterEncoding {
- switch self {
- case .default:
- return URLEncoding.default
- case .json:
- return JSONEncoding.default
- }
- }
- }
- private var method:METHOD = .post
- enum METHOD {
- case get
- case post
-
- func getHTTPMethod() -> HTTPMethod{
- switch self {
- case .get:
- return HTTPMethod.get
- case .post:
- return HTTPMethod.post
- }
- }
- }
-
- private var callBack = MutableProperty<Any?>(nil)
-
- /**
- 초기화
-
- - Parameters:
- - url: String not Optinal 기본주소
- - reqParam: dictionary Optinal 전달 파라메터
- - headerParam: dictionary Optinal 헤더 파라메터
- - fileParam: dictionary Optinal 파일 파라메터
-
- */
- init(_ url:String) {
- super.init()
- self.url = url
- }
-
- /**
- 파라메터설정
-
- - Parameters:
- - type: 딕셔너리
-
- - Returns: self
- */
- func param(reqParam:[String:Any]) -> APIClient {
- self.reqParam = reqParam
- return self
- }
-
- /**
- 파라메터설정
-
- - Parameters:
- - type: 딕셔너리
-
- - Returns: self
- */
- func param(fileParam:[[String:Data]]) -> APIClient {
- self.fileParam = fileParam
- return self
- }
-
- /**
- 파라메터설정
-
- - Parameters:
- - type: 딕셔너리
-
- - Returns: self
- */
- func param(headerParam:[String:String]) -> APIClient {
- self.headerParam = headerParam
- return self
- }
-
- /**
- 인코딩 타입설정
-
- - Parameters:
- - type: ENCTYPE
-
- - Returns: self
- */
- func enType(_ type:ENCTYPE) -> APIClient {
- self.entype = type
- return self
- }
-
- /**
- http 타입설정
-
- - Parameters:
- - type: METHOD
-
- - Returns: self
- */
- func meThod(_ method:METHOD) -> APIClient {
- self.method = method
- return self
- }
-
- /**
- 프로그래스바의 표현여부
-
- - Parameters:
- - isPro: Bool 표현여부
-
- - Returns: self
- */
- func isProgress(_ isPro:Bool) -> APIClient {
- self.progressShow = isPro
- return self
- }
-
- /**
- 파일 업로드를 위한 펑션
-
- - Parameters:
- - multipartFormData: closure로 들어오는 upload 객체
-
- */
- func upload(multipartFormData:MultipartFormData){
- guard let files = self.fileParam else{ return }
- for file in files{
- for (name, data) in file{
- multipartFormData.append(data, withName: name, fileName: "temp.jpg", mimeType: self.mimeTypeForData(data:data))
- }
- }
-
- guard let params = self.reqParam else{ return }
- for (key, val) in params{
- if let strigVal = val as? String{
- multipartFormData.append(strigVal.data(using: .utf8)!, withName: key)
- }else{
- multipartFormData.append(String(describing: val).data(using: .utf8)!, withName: key)
- }
- }
- }
-
- /**
- 콜백 리턴을 넣어주는 펑션
-
- - Parameters:
- - json: closure로 들어오는 DataResponse 객체
-
- */
- func responseJson(json:DataResponse<Any>){
-
- self.callBack.value = json.value as? [String:Any]
- }
-
- /**
- 콜백 리턴을 넣어주는 펑션
-
- - Parameters:
- - data: closure로 들어오는 DataResponse 객체
-
- */
- func responseData(data:DataResponse<Data>){
- self.callBack.value = data.value
- }
-
- /**
- 파일업로드 호출 펑션
- 직접 alamofire를 호출
- */
- func multiUpload(){
- Alamofire.upload(multipartFormData: self.upload,
- usingThreshold: UInt64(),
- to: self.url,
- method: self.method.getHTTPMethod(),
- headers: self.headerParam,
- encodingCompletion:{ encodingResult in
- switch encodingResult {
- case .success(let upload, _, _):
- switch self.returnType {
- case .default:
- upload.responseData(completionHandler: self.responseData)
- case .json:
- upload.responseJSON(completionHandler: self.responseJson)
- }
- case .failure(let encodingError):
- print("error:\(encodingError)")
- }
- })
- }
-
- /**
- 메인 비동기 호출 펑션
- fileParam이 있을경우 self.multiUpload()로 점프한다
- 그외 인코딩 타입에 따라 리스폰스 받은 객체를 completionHandle로 전송한다.
-
- - Parameters:
- - completionHandle: 클로저를 받아 비동기 호출후 값을 담아 전송
-
-
- */
- typealias CallBackHandler<T> = (T) -> Void
- public func connect<T>(completionHandle:@escaping CallBackHandler<T>){
-
- if T.self == [String:Any].self {
- self.returnType = .json
- }else{
- self.returnType = .default
- }
-
- self.callBack.signal.observe { (item) in
- guard let value = item.value as? T else{ return }
-
- completionHandle(value)
- }
-
- guard self.fileParam == nil else {
- self.multiUpload()
- return
- }
-
- let api = Alamofire.request(self.url, method: self.method.getHTTPMethod(), parameters: self.reqParam, encoding: self.entype.getParameterEncoding(), headers: self.headerParam)
- switch self.returnType {
- case .default:
- api.responseData(completionHandler: self.responseData)
- case .json:
- api.responseJSON(completionHandler: self.responseJson)
- }
-
-
- }
-
- /**
- 동기화 호출 펑션
-
- - Returns: DataResponse<Any> JSON OBJECT를 동기화 코드로 전송한다.
- */
- public func get<T>(type:T) -> DataResponse<T> {
-
- if T.self == [String:Any].self {
- self.returnType = .json
- }else{
- self.returnType = .default
- }
-
- let req = Alamofire.request(self.url, method: self.method.getHTTPMethod(), parameters: self.reqParam, encoding: self.entype.getParameterEncoding(), headers: self.headerParam)
-
- let semaphore = DispatchSemaphore(value: 0)
- var result: DataResponse<T>!
- var serializer: DataResponseSerializer<T>!
- switch self.returnType {
- case .default:
- serializer = DataRequest.dataResponseSerializer() as? DataResponseSerializer<T>
- case .json:
- serializer = DataRequest.jsonResponseSerializer() as? DataResponseSerializer<T>
- }
-
- req.response(queue: DispatchQueue.global(qos: .default), responseSerializer: serializer) { response in
- result = response as DataResponse<T>
- semaphore.signal()
- }
-
- _ = semaphore.wait(timeout: DispatchTime.distantFuture)
-
- return result
-
- }
-
- /**
- 파일 타입을 알아내는 펑션
-
- - Parameters:
- - data: Data file 객체
-
- - Returns: String mime 타일을 반납한다. ex) image/jpeg
- */
- public func mimeTypeForData(data:Data) -> String{
- var c = [UInt32](repeating: 0, count: 1)
- (data as NSData).getBytes(&c, length: 1)
- switch (c[0]) {
- case 0xFF:
- return "image/jpeg"
- case 0x89:
- return "image/png"
- case 0x47:
- return "image/gif"
- case 0x49:
- return "image/tiff"
- case 0x4D:
- return "image/tiff"
- case 0x25:
- return "application/pdf"
- case 0xD0:
- return "application/vnd"
- case 0x46:
- return "text/plain"
- default:
- return "application/octet-stream"
- }
- }
-
-
- }
|