import Foundation
//Create an array of landmarks that you initialize from landmarkData.json.
var landmarks: [Landmark] = load("landmarkData.json")
func load<T: Decodable>(_ filename: String) -> T {
let data: Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else {
fatalError("Couldn't find \(filename) in main bundle.")
}
do {
// Data(contentsOf:) ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ํ์ผ์ ๋ด์ฉ์ Data ๊ฐ์ฒด๋ก ์ฝ์ด์จ๋ค.
// ํ์ผ์ ์ฝ๋ ๊ณผ์ ์์ ์์ธ๊ฐ ๋ฐ์ํ ์ ์์ผ๋ฏ๋ก try-catch ๋ฌธ์ ์ฌ์ฉํ์ฌ ์์ธ ์ฒ๋ฆฌ๋ฅผ ํ๋ค.
// ์์ธ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ, fatalError๋ฅผ ํตํด ํ๋ก๊ทธ๋จ์ ์ค์งํ๊ณ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํ๋ค.
data = try Data(contentsOf: file)
} catch {
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
do {
// JSONDecoder ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ , decode(_:from:) ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๋์ฝ๋ฉํ๋ค.
// ๋์ฝ๋ฉํ ํ์
์ T.self๋ก ์ ๋ฌ๋๋ฉฐ, ์ด๋ ์ ๋ค๋ฆญ์ผ๋ก ์ ๋ฌ๋ฐ์ ํ์
T์ ์ค์ ํ์
์ ๋ํ๋
๋๋ค.
// ๋์ฝ๋ฉ ๊ณผ์ ์์ ์์ธ๊ฐ ๋ฐ์ํ ์ ์์ผ๋ฏ๋ก try-catch ๋ฌธ์ ์ฌ์ฉํ์ฌ ์์ธ ์ฒ๋ฆฌ๋ฅผ ํ๋ค.
// ์์ธ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ, fatalError๋ฅผ ํตํด ํ๋ก๊ทธ๋จ์ ์ค์งํ๊ณ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํ๋ค.
// ๋์ฝ๋ฉ์ด ์ฑ๊ณตํ๋ฉด ๋์ฝ๋ฉ๋ ๊ฐ์ธ T๋ฅผ ๋ฐํํ๋ค.
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}
์์ ์ฝ๋๋ ์ ๋ค๋ฆญ ํจ์์ธ load๋ฅผ ์ ์ํ๊ณ ์๋ค. ํ์ผ์์ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ๊ณ , ํด๋น ๋ฐ์ดํฐ๋ฅผ ์ง์ ๋ ํ์
์ผ๋ก ๋์ฝ๋ฉํ์ฌ ๋ฐํํ๋ ์ฝ๋์ด๋ค! Decodable ํ๋กํ ์ฝ์ ์ค์ํ๋ ๊ตฌ์กฐ์ฒด ๋๋ ํด๋์ค ํ์
์ ์ง์ ํ์ฌ load ํจ์๋ฅผ ํธ์ถํ๋ฉด, ํด๋น ํ์ผ์ ๋ฐ์ดํฐ๊ฐ ๋์ฝ๋ฉ๋์ด ํด๋น ํ์
์ ์ธ์คํด์ค๋ก ๋ฐํ๋๋ค. ์ด๋ฅผ ํตํด JSON ๋ฐ์ดํฐ๋ฅผ Swift ๊ฐ์ฒด๋ก ๋ณํํ์ฌ ์ฌ์ฉํ ์ ์๋ค.
file ๋ณ์๋ฅผ ์ต์ ๋ ๋ฐ์ธ๋ฉ → ๋ฉ์๋์ ๊ฒฐ๊ณผ๊ฐ nil์ด ์๋ ๊ฒฝ์ฐ์๋ง file์ ๊ฐ์ด ํ ๋น → ํ์ผ์ ๋ด์ฉ์ Data ๊ฐ์ฒด๋ก ์ฝ์ด์ค๊ธฐ → JSONDecoder ์ธ์คํด์ค๋ฅผ ์์ฑ → decode(_:from:) ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๋์ฝ๋ฉ
๐ค ์ ๋ค๋ฆญ ํ์
T?
์ ๋ค๋ฆญ ํ์ T๋ ํจ์๋ ํ์ ์ ์ ์ํ ๋ ์ค์ ๋ก ์ฌ์ฉ๋ ํ์ ์ ๋ํ๋ด๋ ์ผ์ข ์ ํ๋ ์ด์คํ๋
T๋ ํ์ ํ๋ผ๋ฏธํฐ๋ก์, ํจ์๊ฐ ํธ์ถ๋ ๋ ์ค์ ํ์ ์ผ๋ก ๋์ฒด๋๋ค.
์ ๋ค๋ฆญ์ ์ฌ์ฉํ์ฌ ํจ์๋ ํ์ ์ ์ ์ํ๋ฉด, ์ฌ๋ฌ ๋ค๋ฅธ ํ์ ์ ๋ํด ๋์ํ๋ ์ ์ฐํ๊ณ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๋ค. ํจ์๋ ํ์ ์ ์ผ๋ฐํํ ์ ์์ผ๋ฉฐ, ๋ค์ํ ํ์ ์ ๋ํด ๋์ผํ ๋์์ ์ํํ ์ ์์ต๋๋ค.
์์ ์ฝ๋์์ load ํจ์๋ T๋ผ๋ ์ ๋ค๋ฆญ ํ์ ์ ๋ฐ๋๋ค. ์ด ํจ์๋ฅผ ํธ์ถํ ๋ T์๋ ์ค์ ๋ก ์ฌ์ฉํ ํ์ ์ด ์ง์ ๋๋ค.
์๋ฅผ ๋ค์ด, load<Landmark>("landmarks.json")์ ๊ฐ์ด ํธ์ถํ๋ฉด T๋ Landmark ํ์ ์ผ๋ก ๋์ฒด๋๋ค.
์ ๋ค๋ฆญ์ ์ฌ์ฉํ๋ฉด ์ฝ๋๋ฅผ ํ์ ์ ๋ ๋ฆฝ์ ์ผ๋ก ์์ฑํ ์ ์์ผ๋ฏ๋ก, ํจ์๋ ํ์ ์ ์ฌ์ฌ์ฉํ ์ ์๋ ์ฅ์ ์ด ์๋ค. ๋ค์ํ ํ์ ์ ๋ํด ๋์ํ๋ ๋จ์ผ ํจ์๋ฅผ ์์ฑํ๊ณ , ํด๋น ํจ์๋ฅผ ๋ค์ํ ํ์ ์ผ๋ก ํธ์ถํ ์ ์๋ค. ์ด๋ก์จ ์ฝ๋์ ์ค๋ณต์ ์ค์ด๊ณ ์ ์ง๋ณด์์ฑ์ ํฅ์์ํฌ ์ ์๋ค.
๐ค filename ์์ ๋ถ๋ '_' ๋ ๋ญ๊น?
`load` ํจ์์ ๋งค๊ฐ๋ณ์ `filename` ์์ ๋ถ์ `_`๋ ์์ผ๋์นด๋ ์๋ณ์์ ๋๋ค. ์์ผ๋์นด๋ ์๋ณ์๋ ๋งค๊ฐ๋ณ์ ์ด๋ฆ์ ์๋ตํ๊ณ ์ ํ ๋ ์ฌ์ฉ๋๋ค.
`load` ํจ์๋ ํธ์ถ๋ ๋ ํ์ผ ์ด๋ฆ์ ์ธ์๋ก ์ ๋ฌ๋ฐ์์ผ ํ๋ค. ๊ทธ๋ฌ๋ ํจ์ ๋ด์์๋ `filename`์ ์ฌ์ฉํ์ง ์๊ณ ์๋ค. ๋ฐ๋ผ์, ํจ์ ํธ์ถ์์๊ฒ ํ์ผ ์ด๋ฆ์ ์ ๋ฌํ๊ธฐ ์ํ ๋ชฉ์ ์ผ๋ก ๋งค๊ฐ๋ณ์ ์ด๋ฆ์ ํ์๋ก ํ์ง ์๋๋ค.
์์ผ๋์นด๋ ์๋ณ์ `_`๋ ์ด๋ฌํ ๊ฒฝ์ฐ์ ์ฌ์ฉ๋๋ค. ๋งค๊ฐ๋ณ์ ์ด๋ฆ์ ์๋ตํจ์ผ๋ก์จ ํธ์ถ์์๊ฒ์ ํ์ผ ์ด๋ฆ์ ์ ๋ฌ๋ฐ์ ์ ์๊ฒ ๋๋ค. ํจ์ ๋ด์์๋ ํด๋น ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ์ง ์์ผ๋ฏ๋ก ์๋ตํด๋ ๋ฌธ์ ๊ฐ ์๋ค.
๋ฐ๋ผ์, `func load<T: Decodable>(_ filename: String)`์ ๋งค๊ฐ๋ณ์ `filename`์ ๊ฐ์ง์ง๋ง, ํธ์ถ ์์๋ ํ์ผ ์ด๋ฆ๋ง ์ ๋ฌํ๋ฉด ๋๋ค. `_`๋ ํธ์ถ์์๊ฒ ํด๋น ๋งค๊ฐ๋ณ์์ ์ด๋ฆ์ ๊ฐ์ถ๊ณ ์ถ์ ๋ ์ฌ์ฉ๋๋ ํ๊ธฐ๋ฒ์ด๋ค.
+) ๋งค๊ฐ๋ณ์์ ์ด๋ฆ์ ๊ฐ์ถ์ง ์์ ๊ฒฝ์ฐ ์ฝ๋์ ๋ชจ์ตlet result: MyType = load<MyType>(filename: "data.json")โ
๐ค guard๋ ๋ญ์ง?
guard ๊ตฌ๋ฌธ์ ์ฃผ์ ๋ชฉ์ ์ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋์ง ์์ผ๋ฉด ์กฐ๊ธฐ์ ํจ์๋ฅผ ์ข ๋ฃํ๊ฑฐ๋ ์์ธ ์ฒ๋ฆฌ๋ฅผ ์ํํ์ฌ ์ฝ๋ ์คํ์ ๊ณ์ํ๊ธฐ ์ ์ ์์ธ ์ํฉ์ ์ฒ๋ฆฌํ๋ ๊ฒ
: ์ฝ๋์ ๊ฐ๋ ์ฑ์ ํฅ์, ์กฐ๊ฑด์ ์ถฉ์กฑํ์ง ์์ ๋์ ํน์ํ ์ํฉ์ ๋ช ์์ ์ผ๋ก ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅ
guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else {
fatalError("Couldn't find \(filename) in main bundle.")
}
์์ ์ฝ๋๋ guard ๊ตฌ๋ฌธ์ ์ฌ์ฉํ์ฌ Bundle.main.url(forResource:withExtension:) ๋ฉ์๋์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ธ๋ฉํ๊ณ , ์กฐ๊ฑด์ ์ถฉ์กฑํ์ง ์์ ๊ฒฝ์ฐ fatalError๋ฅผ ๋ฐ์์ํค๋ ์ฝ๋์ด๋ค.
Bundle.main.url(forResource:withExtension:) ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ํ์ผ์ URL์ ๊ฐ์ ธ์จ๋ค. ์ด๋ filename์ ํ์ผ ์ด๋ฆ์ผ๋ก ์ ๋ฌํ๊ณ , withExtension์ ํ์ผ์ ํ์ฅ์๋ฅผ ๋ํ๋ด๋๋ฐ, nil๋ก ์ ๋ฌ๋์ด ํ์ฅ์๋ฅผ ์๋ตํจ์ ์๋ฏธํ๋ค.
guard ๊ตฌ๋ฌธ์ ์กฐ๊ฑด์์๋ file ๋ณ์๋ฅผ ์ต์ ๋ ๋ฐ์ธ๋ฉํ๋ค. Bundle.main.url(forResource:withExtension:) ๋ฉ์๋์ ๊ฒฐ๊ณผ๊ฐ nil์ด ์๋ ๊ฒฝ์ฐ์๋ง file์ ๊ฐ์ด ํ ๋น๋๊ณ , ์กฐ๊ฑด์ ์ถฉ์กฑํ์ง ์์ ๊ฒฝ์ฐ else ๋ธ๋ก์ด ์คํ๋๋ค.
else ๋ธ๋ก ๋ด๋ถ์์๋ fatalError๋ฅผ ํธ์ถํ์ฌ ์ค๋ฅ ๋ฉ์์ง์ ํจ๊ป ํ๋ก๊ทธ๋จ์ ์ค์ง์ํจ๋ค. fatalError ํจ์๋ฅผ ํธ์ถํ๋ฉด ํ๋ก๊ทธ๋จ์ด ์ฆ์ ์ข ๋ฃ๋๋ฉฐ, ์ดํ์ ์ฝ๋๋ ์คํ๋์ง ์๋๋ค.
์ฆ, ์์ ์ฝ๋๋ ํ์ผ์ URL์ ๊ฐ์ ธ์ค๋ ๊ณผ์ ์์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ, ํ๋ก๊ทธ๋จ์ ์ค์งํ๊ณ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํ๋ ๊ฒ์ ๋ชฉ์ ์ผ๋ก ํ๋ค. ์ด๋ ํ์ผ์ ์ฐพ์ ์ ์๋ ์ํฉ ๋ฑ ์์์น ๋ชปํ ์ค๋ฅ์ ๋๋นํ์ฌ ํ๋ก๊ทธ๋จ์ ์์ ์ฑ์ ๋์ด๋๋ฐ ๋์์ ์ค๋ค.
'๐ฑ App > ๐ Swift' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Swift] how to create multiple preview (0) | 2023.06.08 |
---|---|
[Swift] ๋ฐ๋ณต๋ฌธ์์ id: \.id ์ ์๋ฏธ (0) | 2023.06.08 |
[Swift] Swift ์์ Hashable, Codable์ ๋ญ๊น? Protocol ์์๋ณด๊ธฐ (0) | 2023.06.03 |
[SwiftUI] ํท๊น๋ฆฌ๋ State, Binding, ObservedObject, EnvironmentObject ์ด์ ๋ฆฌ (0) | 2023.05.31 |
[SwiftUI Tutorials] SwiftUI Essentials - Creating and Combining Views (0) | 2023.03.26 |
๋๊ธ