A. ์ค๋ช
api ํต์ ํ์ํ ๋๋ง๋ค ๋ณด์ผ๋ฌ ํ๋ ์ดํธ ์ฝ๋๊ฐ ๋๋ฌด ๋ง์ด ์๊ธฐ๋ ๊ฒ ๊ฐ์ base๋ก ์ฌ์ฉํ ์ฝ๋ ๋ง๋ฆ. ํ๋กํ ์ฝ๋ก ์ ์ํด์ ์ฌ์ฌ์ฉ์ฑ ์ฉ์ดํ๋๋ก ๊ตฌํํจ. ์น ์ฐ๊ฒฐ์๋ Alamofire ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํจ.
B. ์ฝ๋
import Foundation
import Alamofire
protocol BaseService {
/// api request url
var url: String { get set }
var header: HTTPHeaders { get set }
var param: Encodable? { get set }
/// Request์ ๋ค์ด๊ฐ๋ .put, .get ๋ฑ method
var method: HTTPMethod { get set }
/// Request์ ๋ค์ด๊ฐ๋ Parameter encoding ๋ฐฉ์
var encoding: ParameterEncoding? { get set }
}
extension BaseService {
/// BaseService์ ์ง์ ํ ๊ฐ์ผ๋ก api ์ฐ๋์ ์ํํ ๊ฒฐ๊ณผ(NetworkResult)๊ฐ closure ํจ์์ param์ด ๋จ.
func serverAction<T>(type: T.Type, completion: @escaping(NetworkResult<Any>) -> Void) where T: Decodable {
var paramAsDictionary: Parameters? = ["Tmp": "Tmp"]
do {
let dictionary = try param?.encode()
paramAsDictionary = dictionary
} catch {
print(error)
}
let dataRequest = AF.request(
url,
method: method,
parameters: paramAsDictionary,
encoding: encoding ?? JSONEncoding.default,
headers: header
)
dataRequest.responseData { response in
switch response.result {
case .success:
guard let statusCode = response.response?.statusCode else { return }
guard let value = response.value else { return }
let networkResult = self.judgeStatus(by: statusCode, value, type: T.self)
completion(networkResult)
case .failure(let error):
print("network err : \(error)")
completion(.networkFail)
}
}
}
func judgeStatus<T>(by statusCode: Int, _ data: Data, type: T.Type) -> NetworkResult<Any> where T: Decodable {
switch statusCode {
case ..<300: return isValidData(data: data, type: T.self)
case 400..<500:
return isErrorData(data: data)
case 500..<600: return .serverErr
default: return .unRecognizedError
}
}
func isValidData<T>(data: Data, type: T.Type) -> NetworkResult<Any> where T: Decodable {
let decoder = JSONDecoder()
guard let decodedData = try? decoder.decode(type, from: data) else {
return .unRecognizedError
}
return .success(decodedData as Any)
}
func isErrorData(data: Data) -> NetworkResult<Any> {
let decoder = JSONDecoder()
guard let errorData = try? decoder.decode(ServerErrorModel.self, from: data) else {
return .unRecognizedError
}
return .pathErr(errorData)
}
}
enum NetworkResult<T> {
/// output data์ ๋ง์ถฐ์ ํ์ฑ๊น์ง ์๋ฃ๋ ๊ฒฝ์ฐ
case success(T)
/// network failure๊ฐ ์๋ ์๋ฌ๊ฐ ๋ฐ์ํ๊ณ
/// api ๋ฌธ์์ ๋ช
์๋ ์๋ฌ data์ ๋ง์ถฐ์ ํ์ฑ๊น์ง ์๋ฃ๋ ๊ฒฝ์ฐ
case pathErr(T)
/// code 500~599๋ก ์๋ฒ ์ชฝ ์๋ฌ์ธ ๊ฒฝ์ฐ
case serverErr
/// ๊ธฐ๊ธฐ ๋คํธ์ํฌ ๋ฌธ์ ์ธ ๊ฒฝ์ฐ
case networkFail
/**
1. network failure๊ฐ ์๋ ์๋ฌ๊ฐ ๋ฐ์ํ์ง๋ง
api ๋ฌธ์์ ๋ช
์๋ ์๋ฌ data์ ๋ง์ถฐ์ ํ์ฑ์ด ๋ถ๊ฐ๋ฅํ ๊ฒฝ์ฐ
2. code๊ฐ 200๋์ด๊ธฐ๋ ํ๋ฐ Service ํธ์ถ์ชฝ์์ ์ ๋ฌํด์ค
data ํ์์ ๋ง์ถฐ ํ์ฑ์ด ๋ถ๊ฐ๋ฅํ ๊ฒฝ์ฐ
3. code๊ฐ 600 ์ด์์ธ ๊ฒฝ์ฐ */
case unRecognizedError
}
// codable -> dictionary Type
extension Encodable {
func encode() throws -> [String: Any] {
let data = try JSONEncoder().encode(self)
guard let dictionary = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any] else {
throw NSError()
}
return dictionary
}
}
C. ์ฌ์ฉ ๋ฐฉ๋ฒ
์ฌ์ฉํ๋ ค๊ณ ํ๋ ์น์๋ฒ ์ฐ๊ฒฐ ํด๋์ค์์ BaseService ์์ ๋ฐ์ ํ url, header, param, method, encoding ๋ณ์ ์ฑ์์ค ํ serverAction()๋ก ๊ฐ ์ผ์ด์ค๋ณ ๋ด์ฉ ๊ตฌํํด์ฃผ๋ฉด ๋จ.
Z. ๋ ํผ๋ฐ์ค
์ด๋ถ๊ฑฐ ์ฐธ๊ณ ํด์ ๊ตฌํํจ : https://roniruny.tistory.com/141
[iOS] Alamofire๋ฅผ ํตํด ์๋ฒ์ ํต์ ํด๋ณด๊ธฐ - GET
์ํธ 4์ฃผ์ฐจ ์ธ๋ฏธ๋ ๋ณต์ต ์ ๋ฆฌ๋ฅผ ์ํ ๊ธ์ ๋๋ค. ๋ค์ ๋์์๋ ๊ธ์์ด ์์๋์ค๋ ๊ทธ๋ฅ ๋ด์ฃผ์ธ์ค. [ Alamofire๋ฅผ ํตํด ์๋ฒ์ ํต์ ํด๋ณด๊ธฐ - GET ] ๐ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ GET ๋ฐฉ์์์๋ ์๋ฒ์์ ์ผ
roniruny.tistory.com
'CS > iOS, Swift' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[iOS] xcode์์ ํ์ ํด๋ ๋ณด์ด์ง ์๋ ๋ฌธ์ (0) | 2023.04.07 |
---|---|
[iOS] unix timestamp swift (0) | 2023.04.07 |
[iOS] ์น๋ทฐ ์ฟ ํค ๊ด๋ จ ์ ํธ (0) | 2023.04.07 |
[iOS] ํค์ฒด์ธ ์ ํธ (0) | 2023.04.07 |
[iOS] ํด์ฑ (0) | 2023.04.07 |