4์ฃผ์ฐจ ๊ธฐ๋ก : ๋คํธ์ํฌ ํต์
๐ง ๋ฌด์์ ๋ฐฐ์ ๋?
- alamofire & swfityJSON์ ์ฌ์ฉํด์ API๋ฅผ ํตํด ์๋ฒ ์๋ต๋ฐ๊ธฐ
- key๋ฅผ .gitignore์ APIKey ํ์ผ์ ๋ง๋ค์ด ๋ฐ๋ก ์ ์ฅํ๊ธฐ (๊นํ์ ์ฌ๋ฆด ๋ ํค ๋ ธ์ถ์ ๋ฐฉ์งํ ์ ์์, ๊ธฐ๋ฐ์ ์ง)
- ๋ก๋ฉ๋ฐ ํ์ฉ ๋ฐ ์ ๋๋ฉ์ด์ ํจ๊ณผ์ฃผ๊ธฐ => ๋ฐ์ดํฐ๊ฐ ์ค๊ณ ์๋์ง ์๋์ง๋ฅผ ์ ์ ์๋ ์ฌ์ฉ์์๊ฒ '๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ณ ์์ด~' ์๋ ค์ฃผ๋ ๊ฒ.
- ์ผ๊ธ๊ฐ์ฒด & ํด๋ก์ (๋ฌธ๋ฒ)
- ํ๊ฐ๊ณผ์ ๊ฐ์ ํ๋ ๋ฐฉ๋ฒ; protocol, userDefaults, singleton
- ๋๊ธฐ/๋น๋๊ธฐ
๐จ ์์
- ์นด์นด์ค ๊ฒ์ API ํ์ฉ
- ๋ค์ด๋ฒ ํํ๊ณ API ํ์ฉ
๐ ๊ณผ์
- ๋ก๋API๋ฅผ ์ด์ฉํด์ ๋ก๋ ๋น์ฒจ๋ฒํธ ์ผ๊ณฑ์๋ฆฌ ๋ฝ์๋ด๊ธฐ. (UIPickerView, textfield๋ฅผ ํฝ์ปค๋ก ์ฌ์ฉํจ)
- bookwarm ํ๋ก์ ํธ ์นด์นด์ค API ๊ธฐ๋ฅ์ ํตํด ์ฑ ๊ฒ์ ๊ธฐ๋ฅ ๊ตฌํํ๊ธฐ.
- ๋๋ค๋งฅ์ฃผAPI๋ฅผ ์ด์ฉํด์ ๋งฅ์ฃผ ์ถ์ฒจํ๋ฉด ๋ง๋ค๊ธฐ. (viewController๋ก ๋จ์ํ ๋ง๋ค๊ธฐ, tableView ์ถ๊ฐํด์ ๋ง๋ค๊ธฐ)
- ๋ค์ด๋ฒ ํํ๊ณ API๋ฅผ ํตํด ๋ฒ์ญ๊ธฐ๋ฅ ๋ง๋ค์ด๋ด๊ธฐ. (์์ ์์ ํ๋ ๊ฒ์์ ์ธ์ด๊ธฐ๋ฅ API ์ถ๊ฐํด์ ๊ธฐ๋ฅ ๊ฐ์ )
๐ฆ ๋ณต๊ธฐ
โ๏ธ [๋ณต์ต] tableView๋ collectionView๋ฅผ XIB ํ์ผ๋ก ๋ง๋ค์ด ์ฐ๋ ๊ณผ์ ๋ฅผ ๋๋ด๊ณ XIB ์์ด viewController์ ์ฐ๋ ค๊ณ ํ๋ ์ธ์คํํฐ ์์ญ์ผ๋ก cellํ์ผ์ ๋ง๋ค๊ณ ์ฐ๊ฒฐ ํ๋ ๊ฑธ ๊น๋จน๊ณ ๋ทฐ์ปจ์ ์์ธ๋ ์ ์ฐ๊ฒฐํ๋ ค ํ๋ค. ๋น์ฐํ ์ฐ๊ฒฐ์ด ์๋์๊ธฐ ๋๋ฌธ์ xcode ์ค๋ฅ์ธ๊ฐ ์ถ์ด์ ์ ๊ฟ์ ๋ทฐ์ปจํธ๋กค๋ฌ ํ์ผ๋ง ๋ฐ๊ณ ๋ค์ ๋ง๋๋๋ผ ์๊ฐ๋ ๊น๋จน์ด์ ๊ฐ์ ์ค์ ๋ ๋ฒ์ ๋ฐ๋ณตํ์ง ์๊ฒ ๋ค๋ ์๋ฏธ๋ก ๋จ๊ธฐ๊ธฐ.
** XIB ํ์ผ ์์ฑํ์ง ์์์ ๋ tableViewCell ์ฐ๊ฒฐ ํ๋ ๋ฐฉ๋ฒ
1. ํ ์ด๋ธ ๋ทฐ ์ ํ
2. ์ ํด๋์ค ์ด๋ฆ ์ฐ๊ฒฐ
3. identifier ์์ง ์๊ณ ์ง์ ํด์ฃผ๊ธฐ.
4. ViewController ์์ญ์ผ๋ก ๋์ด์์ ์ ์ฐ๊ฒฐ ์ง์ด์ฃผ๊ธฐ. ๋!
** (์ถ๊ฐ) XIB ํ์ผ ์์ฑํด์ tableViewCell ์ฐ๊ฒฐ ํ๋ ๋ฐฉ๋ฒ
1. ๋ทฐ์ปจํธ๋กค๋ฌ์ ํ ์ด๋ธ๋ทฐ ์ถ๊ฐํด์ฃผ๊ธฐ.
- ๋ทฐ์ปจํธ๋กค๋ฌ ํ์ผ์ ํ ์ด๋ธ๋ทฐ ์ฐ๊ฒฐ๋ ์์ง ์๊ณ ๋ฐ๋ก ํด์ฃผ๊ธฐ.
2. XIB ํ์ผ์ ์ฒดํฌํ ์ฑ๋ก TableViewCell ํ์ผ ์์ฑํ๊ธฐ
3. ์ ์ด๋ฆ + identifier ์ค์
๋ณดํต XIB ํ์ผ๋ก ๋ง๋ค๋ฉด ์๋์์ฑ ๋์ด ์์ง๋ง, ํน์ ๋ชจ๋ฅด๋ ํ์ธ ํด์ฃผ๊ธฐ.
identifier๋ ์ง์ ์ง์ ํด์ฃผ์ด์ผ ํ๋ค. ์ฌ๊ธฐ๊น์ง ํ๋ฉด cellํํธ์์ ํ ์ผ์ ๋.
4. ๋ทฐ์ปจํธ๋กค๋ฌ์ ์ฝ๋๋ก ์ ์ฐ๊ฒฐํ๊ธฐ
override func viewDidLoad() {
super.viewDidLoad()
trendingTableView.dataSource = self //ํ
์ด๋ธ๋ทฐ ์์ฑ ๊ฐ์ ธ์ค๊ธฐ
trendingTableView.delegate = self //ํ
์ด๋ธ๋ทฐ ์์ฑ ๊ฐ์ ธ์ค๊ธฐ
//์
์ฐ๊ฒฐํด์ฃผ๊ธฐ
let nib = UINib(nibName: "TrendingTableViewCell", bundle: nil)
trendingTableView.register(nib, forCellReuseIdentifier: "TrendingTableViewCell")
}
UINib๊ณผ register ํค์๋๋ก ์ฐ๊ฒฐํด์ฃผ๋ฉด ๋๋ค.
5.
extension TrendingViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TrendingTableViewCell") as! TrendingTableViewCell
}
return cell
}
์ฐ๊ฒฐ๋ ์ ์
let cell = tableView.dequeueReusableCell(withIdentifier: "TrendingTableViewCell") as! TrendingTableViewCell
์ cellForRowAt์ ์จ์ฃผ๋ฉด ๋น๋ํ์ ๋ ์ ์ด ์ ์ฐ๊ฒฐ ๋์ด ์์์ ํ์ธํ ์ ์๋ค.
์ด์ ์ถ๊ฐํ UI ๊ธฐ๋ฅ๋ค์ tableView์ฒ๋ผ extension์ผ๋ก ์ธ ์ค ์์์ ํธํ๋ค.
(+) ํ ์ด๋ธ๋ทฐ๋ ๋ฐ๋ก ๋ ์ด์์์ ์ฝ๋๋ก ์์ฑํ์ง ์๋๋ฏ. ์ด๊ฑธ ๋ชจ๋ฅด๊ณ ์ปฌ๋ ์ ๋ทฐ ๋ ์ด์์ ์ก๋ฏ ์ก๋ค๊ฐ tableViewLayout์ด ์์ด์ ๋นํฉํ๋ค.
โ๏ธ Alamofire์ SwiftyJSON ์ฌ์ฉํด์ API ํต์ ํ๊ธฐ โญ๏ธโญ๏ธ
1. import ํ๋ ๊ฒ ์ฒซ ์์์ผ ํ์๋ ์์ง๋ง, ์๋ฌ ํ์์ค๋ง ๋ณด๋ฉด ์์๋์ด ๋์ Alamofire์ SwiftyJSON์ ์ฌ์ฉํด์ผํ ๋ ๋จผ์ import๋ถํฐ ํด์ค๋ค.
2. Alamofire + SwiftyJSON ๊ตฌ์กฐ ์ดํด.
- - AF๋ Alamofire ์ฝ์์ธ๋ฐ, ๋ ๊ฐ๊ฒฐํ๊ฒ ์ฐ๊ณ ์ ์ ๋ฐ์ดํธ ๋จ.
- - url์ด ๊ธฐ๋ณธ ์ค์ ์ผ๋ก ๋ค์ด๊ฐ ์์ด์, ๋ด๊ฐ ์ฐ๊ณ ์ ํ๋ API๋ฅผ let url = "๋งํฌ"๋ก ์ ์ธํด์ฃผ์ผ ์ฌ์ฉ ๊ฐ๋ฅํ๋ค. (์๋ฌ ๋์ด)
- - Switch ๋ฌธ์ ๋ณด๋ฉด, .success ๊ฐ์ด ๋์ค๋ฉด ๋คํธ์ํฌ ํต์ ์ด ์ ๋๊ณ ์๋ค๋ ์๋ฏธ. .failure ๊ฐ์ด ๋์ค๋ฉด ํต์ ์ ๋ฌธ์ ๊ฐ ์์.
- - json์ API๊ฐ ๋ค์ฌ์ฐ๊ธฐ ๊ธฐ์ค์ผ๋ก ๊ฐ์ ๋ณด์ฌ์ฃผ๊ธฐ ๋๋ฌธ์ json[ ] ํ์์ผ๋ก ๊ฐ์ ๊ฐ์ ธ์์ผ ํ๋ค (ex. . ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ insomnia์์ {์ค๊ดํธ} ํ์ธ์ ์ ํด์ฃผ์ด์ผ ํ๋ค.
- - ๊ฐ์ ธ์จ ๊ฐ [ ] ๋ค์๋ .์ ์ฐ๊ณ stringValue์ธ์ง, intValue์ธ์ง ๋ฑ์ ์ ํ์ธํ๊ณ ๋ถ์ฌ์ฃผ๊ธฐ.
- - insomnia์์ ๋ฏธ๋ฆฌ ๋ค์ฌ์ฐ๊ธฐ ๊ฐ์ ํ์ธํ ์ ์๋ค. ๋์ ์ฌ์ฉํ ๋ API๋ฅผ ์ ๊ณตํ๋ ์ฌ์ดํธ์์ ํ์์กฐ๊ฑด์ด ๋ฌด์์ธ์ง ์ ํ์ธํด์ฃผ์ด์ผํ๋ค. ๊ทธ๋ฆฌ๊ณ ๋ด๊ฐ API ๋ฐ์์ค๋ ์ต์ ์ ๋ญ๋ก ์ ํด๋์๋์ง๋. (๊ธฐ์ตํ์ ๋ค์ด๋ฒ ์ธ์ด๊ฐ์ง API๋ฅผ...๐ช) ๋ณดํต parameters์ header, ์ํธํค๋ง ์ ์ค์ ํด์ฃผ๋ฉด ๋๋ค. ๋คํธ์ํฌ ํต์ ๋ฉ์๋๋!
- - validate์ ํต์ ์ํ๋ฅผ ๋๋ฒ๋ก ๋ํ๋ธ๊ฑด๋ฐ 200๋ฒ๋๊ฐ ์ฐ๊ฒฐ์ํ ์ํธ, 400๋ฒ๋๊ฐ ์ค๋ฅ. ๊ทธ 404๊ฐ ์ฌ๊ธฐ์ ์ํ๋ค.
๊ตฌ์กฐ ์ฐธ๊ณ :
func callRequest() {
let url = "https://์์.์์.์์/์์"
AF.request(url, method: .get).validate().responseJSON { response in
switch response.result {
case .success(let value): // ๋คํธ์ํฌ ํต์ ์ด ์ ๋๋ ์ค
let json = JSON(value)
print("JSON: \(json)")
}
case .failure(let error): // ๋คํธ์ํฌ ํต์ ์คํจ!
print(error)
}
}
}
โ๏ธ HTTPS ๋ง๊ณ HTTP url์ ๊ฐ์ ธ์๋๋ฐ ๋ณด์ ์ค๋ฅ ๋ฐ ๋?
์ด๋ ๊ฒ info์์ ์ค์ ์ ๋ฐ๊ฟ์ฃผ๋ฉด ๋๋ค. ๊ทธ๋ฐ๋ฐ ์ด๊ฑธ ํญ์ ํด์ค์ผํ๋์ง, Alamofire + SwiftyJSON ์ธ ๋ ์๋ตํด๋ ๋๋์ง ์ฐพ์๋ด์ผ ํ ๊ฒ ๊ฐ๋ค. ์ผ๋จ์ ๊ทธ๋ฅ ๋ชจ๋ ํ๋ก์ ํธ์ ์ค์ ํ๊ณ ์๋ ์ค..
โ๏ธ ๋คํธ์ํฌ ๐ฆ
- ๋คํธ์ํฌ ํต์ ์ ๋จ๋ฐฉํฅ ํต์ ์ด๋ผ ํด๋ผ์ด์ธํธ์ ์์ฒญ์ด ์์ด์ผ ์๋ฒ๊ฐ ์๋ต์ ํ๋ค. (ํด๋ผ์ด์ธํธ๊ฐ ๊ฒ์ ๋ฑ์ ํ๋ค. → ์๋ฒ๊ฐ ๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ค๋ค.)
- HttpMethod : Get, Post, Put, Delete (์์ฒญ์ด ์ด ๋ท ์ค ๋ฌด์์ธ์ง ์๋ฒ๊ฐ ๊ตฌ๋ถํด์ ๋ง๋ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ค๋ค.)
- ์ธ์ฆํค (์ฌ์ฉ์๊ฐ ์์ฒญ์ ํ ๋ ์ธ์ฆํค๋ฅผ ์๊ตฌํด์ (์ฌ์ ์ค๋น) ๊ฒ์ฆ๋ ์์๊ฒ๋ง ๋ฐ์ดํฐ๋ฅผ ๊ณต์ ํด์ค๋ค. ์๋ฒ ๋ฐ๋ณด ์๋.)
- API = ํต์ ํ๊ธฐ ์ํด ์ง๊ณ๋ ์ฌ์ดํธ.
- URLSession : API๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๊ธฐ ์ํด ์ ํ์ด ์ ๊ณตํด์ฃผ๋ URL
โ๏ธ ๋ฌธ๋ฒ
* ์ผ๊ธ๊ฐ์ฒด (First Class Object) ์ด๋ฆ ์ ๋๋ง ๊ธฐ์ต๋์ ์ผ๋จ ๊ฐ๋
๋ง ์ ๋ฆฌ
- ๋ณ์/์์๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ ๋ด์ ์๋ฃํ ์ ์ฅ
func rookieDraftBaseball (team : String) -> Bool {
let teamArray = ["๊ธฐ์ ํ์ด๊ฑฐ์ฆ","ํํ ์ด๊ธ์ค","์ผ์ดํฐ ์์ฆ"]
return teamArray.contains(team) ? true : false
} //1. ์๋ฃํ ํจ์ ์์ฑ
let pickTeam = rookieDraftBaseball //2. ์์๋ ๋ณ์์ ํจ์ ์์ฒด๋ฅผ ๋์
pickTeam("๊ธฐ์ ํ์ด๊ฑฐ์ฆ") // true
pickTeam("์์ง ํธ์์ค") // false
๋ง๋ ํจ์์์ ์์๋ ๋ณ์๋ก ์ ์ฅํด์ ์ฌ์ฉํ๋ ๋ฐฉ์.
(+) ํจ์๋ช ์ด ๊ฐ์ผ๋ฉด ํ์ ์ด๋ ธํ ์ด์ ํ์, ํ๋ผ๋ฏธํฐ๊น์ง ๊ฐ์ผ๋ฉด ํจ์ ํ๊ธฐ๋ฒ์ ์ฌ์ฉํด์ ํ์ ์ด๋ ธํ ์ด์ ์๋ตํด์ ์ฌ์ฉ๊ฐ๋ฅ.
- ํจ์์ ๋ฐํ๊ฐ์ผ๋ก ์๋ฃํ์ ์ฌ์ฉ
func yesPostSeaon () -> String {
return "๊ฐ์์ผ๊ตฌ ์ง์ถ"
}
func noPostSeason () -> String {
return "๊ฐ์์ผ๊ตฌ ํ๋ฝ"
}
func forPostSeaon (team : String) -> () -> String {
let teamArray = ["๊ธฐ์ ํ์ด๊ฑฐ์ฆ","ํํ ์ด๊ธ์ค","์ผ์ดํฐ ์์ฆ"]
return teamArray.contains(team) ? yesPostSeaon : noPostSeason
}
let call = forPostSeaon(team:"๊ธฐ์ ํ์ด๊ฑฐ์ฆ")
call() // ๊ฒฐ๊ณผ๊ฐ: "๊ฐ์์ผ๊ตฌ ์ง์ถ"
์ ์ผ ์ฒ์ ๋์ค๋ -> ๋ฅผ ๊ธฐ์ค์ผ๋ก ์ค๋ฅธ์ชฝ์ด ๋ฐํ๊ฐ์ ์๋ฏธ.
func forPostSean (team : String) -> () -> String
๋ฆฌํด๋์ด ๋์ค๋ ํจ์๋ ์ฆ ์ค๋ฅธ์ชฝ ๋ฐํ๊ฐ.
- ํจ์์ ์ธ์๊ฐ์ผ๋ก ์๋ฃํ์ ์ ๋ฌ
์... ์ผ๋จ ๋ณด๋ฅ. ์์๊ณผ ๊ด๋ จ๋ ์ ๋ฌ๋ฐฉ๋ฒ๊ฐ์๋ฐ ๋ณด๋ฉด ๋ณผ์๋ก ํท๊ฐ๋ฆฐ๋ค. string์ int๋ก ๋ฐํํด์ฃผ๋.. ๊ฑด๊ฐ? ์๋ฌด๋๋ ๊ฐ์ฅ ํด๋ก์ ๊ฐ๋ ์ด๋ ๋น์ทํด์ ์ ์๋ฟ๋ ๊ฒ ๊ฐ๋ค. ๋์ค์ ๋ณด๊ฐํ๊ธฐ.
โ๏ธ ๋๊ธฐ์ ๋น๋๊ธฐ
๐ ํ๋์บ๋ฆฌํ๋ ๋ญ ์๋ฐ์ ์๊ฐํ๊ธฐ
- ๋๊ธฐ (Sync): Queue(๋งค๋์ )์ ๋ค์ด๊ฐ ์์ ์ด ๋๋ ๋๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ ๋ฉ์ธ์ฐ๋ ๋(๋ญ)์ด ๋ค์ ์์ ์ ํ๋ ๊ฒฝ์ฐ.
- ๋น๋๊ธฐ(Async): ๋ฉ์ธ์ฐ๋ ๋๊ฐ ์ฌ๋ฌ ๊ฐ์ task๋ฅผ ๋ด๋นํ๊ณ ์๋ ๊ฑธ ๋ค๋ฅธ ์ฐ๋ ๋๋ค๊ณผ ์ญํ ๋ถ๋ด์ ํ๋ค (- >concurrent). (ํ์๊ฒ ๋ณด๋ด๋๊ณ ๋ฐ๋ก ๋ค์ ์์ ํ ๊ฒ~ task 1,2๋ฅผ ์ฃผ๋ฉด task3๋ฅผ ๋ฐ๋ก ์์)
- ํ(queue)๋ task๋ฅผ ๋ถ๋ฐฐํ๋ ์ญํ .
๋์ ๊ตฌ์กฐ:
- ํ๊ฐ ๋ถ๋ฐฐ๋ฅผ ํ๊ธด ํ๋๋ฐ ๊ฑฐ์ ๋ฉ์ธ ์ฐ๋ ๋์ ๋ชฐ์์ค๋ค = ์ง๋ ฌ (serial)
- ์ฌ๋ฌ ์ฐ๋ ๋๋ค์ ๊ณจ๊ณ ๋ฃจ ๋ถ๋ฐฐํด์ฃผ๋ ๊ฒ : concurrent (global)
- dispatchQueue + main (serial๋ก ๋์)/ global (concurrent๋ก ๋์) : ์๋ฃ ํต์ ์ ๊ตฌ์กฐ๋ฅผ ๊ฒฐ์ ํ๋ค.
- ์ ์ฌ์ฉํ์ง ์๋ ๊ฒ: global.sync→ ๊ฒฐ๊ตญ์ ๋ฉ์ธ์ด ์ผ์ ํจ, main.async → ํ๊ฐ ์๋ฌด๊ฒ๋ ๋ชปํจ.
- global.async์ ์ฅ์ :
- ๋ ๋นจ๋ฆฌ ๋๋๋ค.
- ์ด๋ค ์์ ์ด ์ธ์ ๋๋ ์ง ๋ชจ๋ฅธ๋ค. (๊ทธ๋๋ ์ธ์ ๊ฐ ๋๋๊ธด ๋๋จ)
์์ฝ:
main.async → UI update
global.async → network ๋ด๋น
์ธ์์์ ์ฝ๋ฉ์ ์์ํ์ง ํ๋ฌ ์ฐจ์ ๋:
'๐ฑ SeSAC iOS 3๊ธฐ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๐ฑ ์์น ์๋ฑํฌ iOS ์ฑ๊ฐ๋ฐ์ ๋ฐ๋ท๊ณผ์ 3๊ธฐ ํ๊ธฐ (3) | 2024.06.25 |
---|---|
[SeSAC] iOS ๊ฐ์ธ์ฑ <์ง๊ด๋ก๊ทธ> ์ถ์ ํ๊ณ (10) | 2023.10.24 |
๐ฑ 7์ฃผ์ฐจ: URLSession, Access Control, ARC (4) | 2023.09.04 |
๐ฑ 6์ฃผ์ฐจ: NotificationCenter, CLLocationManager, MKMapView, UIPageViewController (1) | 2023.08.27 |
๐ฑ 5์ฃผ์ฐจ: API ํต์ , Codable, DispatchGroup, ๋ณต์ต (1) | 2023.08.20 |