์์ ํฌ์คํ ๊ธ๋ค์ ์ข ํฉํ!!
์์ ํฌ์คํ ํ๊ฒ๋ค์ ๋์ดํด๋ณด๋ฉด
- Alamofire: ํต์ ์ ์ฝ๊ฒ ํด์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
- Codable: Swift4๋ถํฐ ์๊ธด๊ฒ์ผ๋ก JSON ๋ฐ์ดํฐ๋ฅผ ๊ตฌ์กฐ์ฒด๋ก ๋ง๋ค์ด์ฃผ๋ ๊ต์ฅํ ์ข์ ํ๋กํ ์ฝ
- Escaping: ๋น๋๊ธฐ์ ํจ์(ex: Alamofire)๋ผ ๋ถ๊ฐ๋ฅํ๋ return๊ฐ ์ฒ๋ฆฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํ๋ ๋ฐฉ๋ฒ
ํฌ๊ฒ ์ด๋ ๊ฒ 3๊ฐ์ง์ ์ฃผ์ ๋ก ์งํ ๋์๋ค๊ณ ๋ณผ ์ ์์ต๋๋ค. ์ด๋ฒ์ ํ๊ฒ๋ ๊ฒ์ ์ด๊ฒ๋ค์ ์ข ํฉํ์ด๋ผ ์๊ฐํ๋ฉด ๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ฌ๊ธฐ๊น์ง ์ค๊ฒ๋ ์ด์ ๋ ๊ฐ๋ฐ์ ํ๋ฉด์ ๋๋๊ฒ์ด์ง๋ง, ํต์ ์ด ๊ต์ฅํ ๋ง์๋ฐ ์ด๊ฒ๋ค์ ์๊ธฐ ์ ๊น์ง ๊ต์ฅํ ๋ฐ๋ณต์ ์ธ ์ฝ๋๋ฅผ ๊ณ์ ์ฌ์ฉํด์๋ค๋ ๊ฒ์ ๋๊ผ์ต๋๋ค.
๊ทธ๋์ ์ด๋ป๊ฒํ๋ฉด ๋ฐ๋ณต์ ์ค์ผ๊น?๋ก ์์ํด์ Codable, Escaping, Generic ๋ฑ๋ฑ์ ์ตํ๊ฐ๋ฉด์ ์ ์ฉํ๊ฒ ๋์์ต๋๋ค.
์ต์ข ์ ๋ชฉํ๋ ๋ฐ๋ณต์ ์ค์ฌ ๋ถํ์ํ ์ฝ๋ ์ค์ด๊ณ ์ฌ์ฉํ๊ธฐ ์ฝ๊ฒ ๋ง๋ค๊ธฐ ์ด๊ฒ์ด ๋ชฉํ์ ๋๋ค
Q. ๊ฐ์
์ฌํ๊ป ํ๋๊ฒ์ผ๋ก๋ ์ถฉ๋ถํ ์๊ฐ๊ณผ ์ฝ๋๋ฅผ ์ค์ผ ์ ์์ต๋๋ค. ๊ทธ๋ ์ง๋ง! Codable์ ์ฌ์ฉํ ํํ๊ฐ ๋ง์์ง๋ค๋ฉด? ๋ณต์กํด์ง๊ฒ์ ๋๋ค.
์ฐ์ ๊ตฌ์กฐ์ฒด 1๊ฐ๊ฐ ์์ต๋๋ค.
struct StructA: Codable {
var hp: String?
var name: String?
var age: Int?
}
์ด 3๊ฐ์ ๊ตฌ์กฐ์ธ๋ฐ์, ์์ ํฌ์คํ ํ๋ Codable๊ณผ Escaping์ ์ด์ฉํ๋ค๋ฉด Alamofire๋ฅผ ํตํด ์ป์ ์๋ต๊ฐ์ ์ฝ๊ฒ ํด๋น ๊ตฌ์กฐ์ฒด์ ๊ฐ์ฒด๋ฅผ ์ป์ด๋ผ ์ ์์ต๋๋ค.
๋ค๋ฅธ ๊ฐ์ ์ ๋ณด๊ฒ ์ต๋๋ค.
struct StructA: Codable {
var hp: String?
var name: String?
var age: Int?
}
struct StructB: Codable {
var country: String?
var address: String?
}
struct StructC: Codable {
var data1: StructA?
var data2: StructB?
}
์ด๋ฒ์ ๊ตฌ์กฐ์ฒด๊ฐ 3๊ฐ ์ ๋๋ค. URL๋ 3๊ฐ๋ฅผ ์ฌ์ฉํ ๊ฒ ์ ๋๋ค! ๊ทธ๋ ๋ด ์ฌ๊ธฐ์ Codable / Escaping / Alamofire๋ฅผ ๋๊ฐ์ด ์ด์ฉํ๋ ค๋ฉด 3๊ฐ์ง์ Decodable ํจ์๊ฐ ์์ด์ผ ํ ๊น์?
๋ค ์์ด์ผํฉ๋๋ค.
Generic์ ์ฌ์ฉํ์ง ์๋๋ค๋ฉด ๋ง์ด์ฃ .
Generic
์์ด ์ฌ์ generic
- ์ผ๋ฐ์ ์ธ
- ํฌ๊ด์ ์ธ
- ์ด์นญ์ ์ธ
์ ๋ค๋ฆญ์ ๋ค์ ๋ฏ์ค์๋ ์์ต๋๋ค. ์ ๋ ์ฑ ์์ ๋ดค์ง๋ง ์ฑ ์์ ๋น์ค๋ ํฌ์ง ์์๊ณ , ์์๋ ์์์ผ๋ ์ด๋ป๊ฒ ์ฌ์ฉํ ์ง ๋ชฐ๋์ต๋๋ค.
์์ด์ฌ์ ์์ 1๋ฒ์ ์๋ฏธ์ ๊ฐ์ด ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ๋ก ๋ง๋ค์ด์ค ์ ์์ต๋๋ค.
์ด์ ๋ ๋ง๋ก๋ ์ดํด๊ฐ ํ๋ค๊ธฐ์ ์ฝ๋๋ก ์ค๋ช ์ ํ๊ฒ ์ต๋๋ค. ์๋๋ ์ ํ์์ ์ ๊ณตํ๋ ์์์ ๋๋ค.
// ๋ ์ซ์ ๋ณ๊ฒฝ
func swapTwoInts(_ v1: inout Int, _ v2: inout Int) {
let temp = v1
v1 = v2
v2 = temp
}
var value1: Int = 10
var value2: Int = 20
print("value1 = \(value1), value2 = \(value2)")
// ํจ์ ํธ์ถ
swapTwoInts(&value1, &value2)
print("value1 = \(value1), value2 = \(value2)")
์ด๋ ต์ง ์์ ์ฝ๋์ ๋๋ค. ๋๊ฐ์ง ์ธ์๋ฅผ ๋ฃ๊ณ ์๋ก ๊ฐ์ ๋ฐ๊ฟ์ฃผ๋ ๊ฒ์ด๊ณ ,
ํจ์์ธ์ ํ์ ์ inout์ด ๋ถ์ ์ด์ ๋ ์ธ๋ถ์ ๋ณ์๊ฐ์ ๋ฐ๊ฟ์ฃผ๊ธฐ ์ํด์ ์ ๋๋ค. ๋ณดํต์ ๊ฒฝ์ฐ ๊ฐ์ด ๋ณต์ฌํด์ ๋ค์ด๊ฐ๊ธฐ ๋๋ฌธ์ ํจ์๋ด์์ inout์ด ์๋ค๋ฉด v1๊ณผ v2์ ๊ฐ์ ํ ๋นํ ์ ์์ต๋๋ค.
inout์ ์ ์ฉํด์ค๋ค๋ฉด ์ด๋ฅผ ๊ฐ๋ฅ์บํฉ๋๋ค. ํจ์ ํธ์ถ ์ฝ๋๋ณด๋ฉด &๊ฐ ์์ต๋๋ค.
c์ธ์ด๋ฅผ ๋ฐฐ์ฐ์ จ๋ค๋ฉด ํฌ์ธํฐ ๋ถ๋ถ์์ &๋ฅผ ์ด์ฉํ์ฌ ์ฃผ์๊ฐ์ ์ฌ์ฉํ ์ ์์์ต๋๋ค. ๊ทธ์ ๋ง์ฐฌ๊ฐ์ง๋ก ์๊ฐ์ด ๋๋ฉฐ
์ค์ value1๊ณผ value2๊ฐ ์๋ ์ฃผ์ ๊ฐ์ ํจ์์ ๋ฃ๊ธฐ ๋๋ฌธ์ ํจ์์์ ๊ฐ ๋ณ๊ฒฝ์ ์ค์ ๋ก ๋ณ๊ฒฝ์ด ๋ฉ๋๋ค.
๊ทธ๋ฐ๋ฐ, Intํ๋ง ํด๋น์ด ๋๊ธฐ๋๋ฌธ์ String์ด๋ Double์ผ ๊ฒฝ์ฐ ์ฌ์ฉ์ด ๋ถ๊ฐ๋ฅํ ํจ์์ ๋๋ค.
์ค๋ฒ๋ผ์ด๋๋ฅผ ์ฌ์ฉํด์ ๋ชจ๋ ํ์ ์ ํด์ผํ ๊น์? ๊ทธ๋ฌ๋ฉด ๊ต์ฅํ ๋ถํธํ ๊ฒ์ ๋๋ค.
์ด๋ฐ ๋ฌธ์ ๊ฐ ์์ ๋, Generic์ด ์ฌ์ฉ๋ฉ๋๋ค.
// ๋ ๋ณ์๊ฐ ๊ตํ
func swapTwoInts<T>(_ v1: inout T, _ v2: inout T) {
let temp = v1
v1 = v2
v2 = temp
}
์ฌ๊ธฐ์ T๊ฐ ์ถ๊ฐ๋์๋๋ฐ์, ๋ฏ์ค์ ์์ง๋ง ๊ฐ๋จํฉ๋๋ค. T๋ ์ ๊ฐ ์์๋ก ์ ์ด์ ๋ง๋ ์ ๋ค๋ฆญ ํ์ ๋ช ์ ๋๋ค.
๊ทธ๋ ๋ค๋๊ฑด T๊ฐ ์๋๋ผ V๊ฐ ๋ ์๋ ์๊ณ Test๊ฐ ๋ ์๋ ์๊ณ ๋ง์๋๋ก ์ ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก T๋ฅผ ์ฐ๋๊ฒ ๊ฐ๋๊ตฐ์.
Stringํ๊ณผ Intํ์ ์ ๋ค๋ฆญ์ ์ด์ฉํ ํจ์ ํ๋๋ก ์ฌ์ฉํ ๊ฒฐ๊ณผ ์ ๋๋ค.
ํจ์ ํ๋๋ฅผ ์ผ๋ฐ์ ์ธ ํํ๋ก ์ฌ์ฉํ๊ฒ ๋์์ต๋๋ค! โ์ผ๋ฐ์ ์ธ ํํ๋กโ ยซย โ์ผ๋ฐ์ โ ยซย โGeneric!!โ ํ
๊ทธ๋ ๋ค๋ฉด ์ด๋ฐ์ผ๋ก ๋์๊ฐ ๊ฐ์ ์ด์๋, 3๊ฐ์ง ๋ค๋ฅธ ๊ตฌ์กฐ์ฒด๋ฅผ Codable์ ์ด์ฉํ์ฌ ๊ฐ์ฒด๋ก ๋ง๋ค์ด์ฃผ๋ ํจ์๋ฅผ
3๊ฐ ๋ง๋๋๊ฒ ์๋๋ผ ์ผ๋ฐ์ ์ผ๋ก ์ฐ์ผ ํจ์๋ฅผ ์ ์ฉํ๋๊ฒ ์ด ๊ธ์ ์ต์ข ๋ชฉ์ ์ ๋๋ค.
Enum
์ฐ์ enum์ ์ด์ฉํด url๋ค์ ์ ์ํ๊ณ ์ด๋ฅผ ์ด์ฉํ๋ ํจ์๋ ๋ง๋ค์์ต๋๋ค.
enum ListURL: String {
case url1 = "http://localhost/Generic1.php"
case url2 = "http://localhost/Generic2.php"
case url3 = "http://localhost/Generic3.php"
func alamofireDefault(handler: @escaping (NSDictionary?)->Void) {
// url ์ ์
let url = self
// ํต์ ์งํ
let network = Alamofire.request(url.rawValue)
// ํต์ ์๋ต
network.responseJSON { (response) in
switch response.result {
case .success(let object):
// NSDictionary ํํ๋ก ๋ณ๊ฒฝ
guard let nsDic = object as? NSDictionary else {
// ์บ์คํ
์คํจ
handler(nil)
return
}
// ์บ์คํ
์ฑ๊ณต & ๋ฐํ
handler(nsDic)
break
case .failure(let e):
// ํต์ ์คํจ
print(e.localizedDescription)
handler(nil)
}
}
}
}
์์ ํฌ์คํ ์ ๋๋ถ๋ถ์ด ์ ๊ธฐ์ ๋ค์ด๊ฐ์์ต๋๋ค. enum, Alamofire, Escaping!
Enum(์ด๊ฑฐํ)์ ์ฅ์
์ ์ธํ ์ผ์ด์ค ์ธ์๋ ์ ์ฉ ๋ถ๊ฐ๋ฅ -> ์ค๋ฅ ๊ฐ๋ฅ์ฑ ๋ฎ์ถค
์ด๊ฑฐํ ์์ ๊ด๋ จ ํจ์๋ ๋ง๋ค์ด์คฌ์ต๋๋ค. ์ฌ์ฉ์ ์ด๋ป๊ฒ ํ ๊น์?
// ์ ์ธ
let url: ListURL = .url1
// ListURL ์์ ํจ์ ํธ์ถ
url.alamofireDefault(type: StructA()) { (nsDic) in
if let value = nsDic {
print(value)
}
}
๊ฒฐ๊ณผ๊ฐ์ ๋ณด๊ธฐ์ ์ ๊ฐ url์ JSON ํํ์ ์๋ต๊ฐ๋ค์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค
//url1
{"hp":"01012341234","name":"KJS","age":27}
//url2
{"country":"Korea","address":"Seoul"}
//url3
{"data1":{"hp":"01012341234","name":"KJS","age":27},"data2":{"country":"Korea","address":"Seoul"}}
url3์ ๊ฒฝ์ฐ data1์๋ url1์ ์๋ต๊ณผ ๊ฐ์ ๊ฐ, data2์ ๊ฒฝ์ฐ๋ url2์ ์๋ต๊ฐ๊ณผ ๊ฐ์ ๊ฐ์ ๋๋ค.
url1๋ง ๊ฒฐ๊ณผ๋ ์ฝ๊ฒ ๋์๊ตฌ์!
๊ทผ๋ฐ ์ฌ๊ธฐ์ Codable์ ์ฐ์ง ์๊ณ NSDictionary ํํ๋ก๋ง ์บ์คํ ํ ๋๋ ค์คฌ์ต๋๋ค.
๊ทธ๋ผ ์ด๋ ์ํฉ์ ๋ฐ๋ผ Codable์ ์ด์ฉํ ๊ฒ์ ๋๋ค.
๋ณ๊ฒฝ์
// ์ ์ธ
let url: ListURL = .url1
// ListURL ์์ ํจ์ ํธ์ถ
url.alamofireDefault(type: StructA()) { (nsDic) in
if let value = nsDic {
print(value)
}
}
๋ณ๊ฒฝํ
let url: ListURL = .url1
url.alamofireDefault(type: StructA()) { (nsDic) in
if let value = nsDic {
do {
// JSON์ผ๋ก ๋ณํ
let data = try JSONSerialization.data(withJSONObject: value, options: .prettyPrinted)
// Decodable ์ฌ์ฉ
let codableObject = try JSONDecoder().decode(StructA.self, from: data)
print("""
hp : \(codableObject.hp!)
name : \(codableObject.name!)
age : \(codableObject.age!)
""")
} catch {
print(error.localizedDescription)
}
}
}
์ดํด๊ฐ ์๋๋ค๋ฉด ์๋ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํด์ฃผ์ธ์
์ดํด๊ฐ ๋๋จ ๊ฐ์ ํ์ ํฌ์ธํธ๋ Decodable ์ฌ์ฉ ๋ถ๋ถ์ ๋๋ค
decodeํจ์์ ์ธ์๊ฐ 2๊ฐ์ง ์ ๋๋ค. Decodableํ๋กํ ์ฝ๊ณผ ๋ฐ์ดํ
์ฌ๊ธฐ์ from๋ถ๋ถ์ JSON๋ณํ๋ ๋ฐ์ดํฐ๋ ๊ณตํต ์ฌ์ฉ์ด ๋์ง๋ง, ์ฒซ๋ฒ์งธ ์ธ์์ ๊ฒฝ์ฐ๋ ์ฌ์ฉ์ด ์๋ฉ๋๋ค.
์ด๋ฅผ ํจ์๋ก ๋ฐ๊ฟ๋ ๊ต์ฅํ ๋๊ฐํ ๊ฒ์ ๋๋ค.
์ Genericํํธ ์ฒ๋ผ ์ฌ๋ฌ๊ฐ๊ฐ ์ฌ์ฉ์ด ๋ ๊ฒ์ ๋๋ค.
Genericํํธ์์ ํด๋น ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ฒ์ฒ๋ผ ์ฌ๊ธฐ์๋ Generic์ ์ด์ฉํด๋ด ์๋ค.
ํจ์๋ฅผ ํ๋ ๋ง๋ญ๋๋ค.
func useDecodable<T>(type: T, nsDic: NSDictionary) -> T? {
// JSON ๋ณํ
do {
// JSON ๋ณํ
let JSONData = try JSONSerialization.data(withJSONObject: nsDic, options: .prettyPrinted)
// Decodable์ ์ด์ฉํด ๊ฐ์ฒด๋ฅผ ์ป์
let data = try JSONDecoder().decode(T.self, from: JSONData)
// data ๋๋ ค์ฃผ๊ธฐ
return data
} catch {
// ์๋ฌ์ ์ถ๋ ฅ
print(error.localizedDescription)
// nil๋๋ ค์ฃผ๊ธฐ
return nil
}
}
T๋ผ๋ ํ์ ์ ์ ๋ค๋ฆญ ํ์ ์ ๋ง๋ค์๊ณ ๋ฌธ์ ๊ฐ ๋์๋ decode์ชฝ์ ๋ณด๋ฉด ์๋์ ๊ฐ์ต๋๋ค
// ์ผ๋ฐ์ ์ธ ํ์
์ ๋ฃ์ T.self
let data = try JSONDecoder().decode(T.self, from: JSONData)
์์ ๊ฐ์ด ์ผ๋ฐ์ ์ธ ํ์ ์ด ๋ค์ด๊ฐ๊ฒ ๋ฉ๋๋ค.
( ์ฃผ์ !! ์ด ๋ฐฉ์์ ๋จ์ ์ type์ด๋ผ๋ ์ธ์๋ ํ์ ๋ง ์ฃผ๊ธฐ์ํด ๊ฐ์ ธ์ฌ๋ฟ ์ค์ ๋ก ์ฌ์ฉ์ด ๋์ง ์๋๋ค๋ ๋จ์ ์ด ์์ต๋๋ค. )
์คํ์ด ๋ ๊น์?
๋ค ์๋ฉ๋๋ค. ๊ทธ ์ด์ ๋ ๋ญ๊น์? ๊ฒฐ๋ก ์ ์๊ธฐํ๋ฉด ์ ๋ค๋ฆญ ํ์ ์ธ T๋ Decodable ํ๋กํ ์ฝ์ด ์๋ค๋ ๊ฒ ์ ๋๋ค.
์ ๋ค๋ฆญ T์ ํ๋กํ ์ฝ์ ์ถ๊ฐํด์ฃผ๋ฉด ๋ฉ๋๋ค. ์ด๋ ๊ฒ
func useDecodable<T: Codable>(type: T, nsDic: NSDictionary) -> T? {}
ํจ์๋ช ์์ ์๋ T ํ์ดํ๊ดํธ ์์ ์์ ๊ฐ์ด ์ ์ํด์ฃผ๋ฉด ๋ฉ๋๋ค.
๋ณต๋ถ์ ํ ๋๊ตฐ๊ฐ ์์์ง ๋ชจ๋ฅด๊ฒ ์ง๋ง ํธ์๋ฅผ ์ํด ํ์ฝ๋!
func useDecodable<T: Codable>(type: T, nsDic: NSDictionary) -> T? {
// JSON ๋ณํ
do {
// JSON ๋ณํ
let JSONData = try JSONSerialization.data(withJSONObject: nsDic, options: .prettyPrinted)
// Decodable์ ์ด์ฉํด ๊ฐ์ฒด๋ฅผ ์ป์
let data = try JSONDecoder().decode(T.self, from: JSONData)
return data
} catch {
print(error.localizedDescription)
return nil
}
}
์๋ฌ๋ ์ฌ๋ผ์ก์ต๋๋ค.
๊ทธ๋ผ ์ฌ์ฉ๋ฒ์ชฝ์ผ๋ก ๊ฐ์
๋ณ๊ฒฝ์
// ์ ์ธ
let url: ListURL = .url1
// ListURL ์์ ํจ์ ํธ์ถ
url.alamofireDefault(type: StructA()) { (nsDic) in
if let value = nsDic {
print(value)
}
}
๋ณ๊ฒฝํ
let url: ListURL = .url1
url.alamofireDefault(type: StructA()) { (nsDic) in
if let value = nsDic {
switch url {
case .url1:
let object = self.useDecodable(type: StructA(), nsDic: value)
print(object!)
case .url2:
let object = self.useDecodable(type: StructB(), nsDic: value)
print(object!)
case .url3:
let object = self.useDecodable(type: StructC(), nsDic: value)
print(object!)
}
}
}
switch๋ฅผ ์ด์ฉํด ๊ฒฝ์ฐ๋ฅผ ๋๋์๊ณ , ์ด๋ ๋ณด์ฌ์ฃผ๊ธฐ ์ํด ๋ค ์ผ์ต๋๋ค. ๋ค๋ฅด๊ฒ ์ ๋์ ์ผ๋ก ํ์ฉํ๋ฉด ์ข์๊ฒ์ ๋๋ค!
์ง๊ธ ์ ์ํ๋ ๋จ์ํ ๋ณด์ฌ์ฃผ๊ธฐ ์ํจ์ ๋๋ค~!
ํฌ์ธํธ๋!! ํจ์ ํ๊ฐ์ง๋ฅผ ๊ฐ์ง๊ณ ์๋ก ๋ค๋ฅธ ๊ตฌ์กฐ์ฒด์ผ์ง๋ผ๋ Codable์ ์ด์ฉํ ์ ์๋ค๋ ์ ์ ๋๋ค. ์ค์ ๋ก๋ ์ ํจ์๋ง ํ์ํ ๋ ๋ฐ๋ก ์ฌ์ฉ์ ํ๊ฒ ์ฃ ?
๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด
URL 1์ ๊ฒฝ์ฐ
URL 2์ ๊ฒฝ์ฐ
URL 3์ ๊ฒฝ์ฐ
๋ชจ๋ ์๋์์ฃ ???
์ ๊ฐ์ ๊ฒฝ์ฐ ์ด๋ฐ๊ฒ์ ์ด์ฉํด์ ์ข ๋ ํธํ๊ฒ ์ค์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค! ์ข๋ ํธํ ๋ฐฉ๋ฒ์ ์ฐพ์ ๋ฐ๊ฒฌํ๋ฉด ํฌ์คํ ํด์ผ๊ฒ ์ต๋๋ค.
์ด๋ก์จ Alamofire, Codable, Escaping, Generic์ ๋ชจ๋ ์ฌ์ฉํ ์ด๋ฒ ํฌ์คํ ์ ๋ง์นฉ๋๋ค!