jacobkosmart / covidApp-iOS-practice

To practice alamofire, cocoapods and charts library

Home Page:https://jacobko.info/uikit/ios-08/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

πŸ’‰ CovidApp-iOS-practice

스크란샷

πŸ“Œ κΈ°λŠ₯ 상세

  • μ‹œλ„λ³„ μ‹ κ·œ ν™•μ§„μž μˆ˜κ°€ 파이 차트둜 ν‘œμ‹œ λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€

  • λ„μ‹œ ν•­λͺ©μ„ μ„ νƒν•˜λ©΄ 상세 ν˜„ν™©μ„ λ³Ό 수 μžˆλŠ” ν™”λ©΄μœΌλ‘œ μ΄λ™λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.

πŸ”‘ Check Point !

image

πŸ”· App Model

// in CityCovidOverView.swift

import Foundation

struct CityCovidOverView: Codable {
	let korea: CovidOverview
	let seoul: CovidOverview
	let busan: CovidOverview
	let daegu: CovidOverview
	let incheon: CovidOverview
	let gwangju: CovidOverview
	let daejeon: CovidOverview
	let ulsan: CovidOverview
	let sejong: CovidOverview
	let gyeonggi: CovidOverview
	let gangwon: CovidOverview
	let chungbuk: CovidOverview
	let chungnam: CovidOverview
	let jeonbuk: CovidOverview
	let jeonnam: CovidOverview
	let gyeongbuk: CovidOverview
	let gyeongnam: CovidOverview
	let jeju: CovidOverview
}

struct CovidOverview: Codable {
	let countryName: String
	let newCase: String
	let totalCase: String
	let recovered: String
	let death: String
	let percentage: String
	let newCcase: String
	let newFcase: String
}

// in CovidTime.swift

import Foundation
struct CovidTime: Codable {
	let updateTime: String
}

πŸ”· ꡿바이 μ½”λ‘œλ‚˜ 19 API

Corona-19-API - https://github.com/dhlife09/Corona-19-API

πŸ”· Alamofire

  • Alamofire λŠ” Swift 기반의 HTTP λ„€νŠΈμ›Œν‚Ή 라이브러리 μž…λ‹ˆλ‹€. URLSession 을 기반으둜 ν•œ λΌμ΄λΈŒλŸ¬λ¦¬λ‘œμ„œ, λ„€νŠΈμ›Œν‚Ή μž‘μ—…μ„ λ‹¨μˆœνžˆ ν•˜κ³  λ„€νŠΈμ›Œν‚Ήμ„ μœ„ν•œ λ‹€μ–‘ν•œ method, json parsing 등을 제곡 ν•©λ‹ˆλ‹€.

Alamofire μ£Όμš” νŠΉμ§•

  • μ—°κ²° κ°€λŠ₯ν•œ request, response method λ₯Ό μ œκ³΅ν•˜λ©°, URL json parameter encoding 을 지원 ν•©λ‹ˆλ‹€. 파일 데이터 슀트리밍, multi part form date λ“± upload κΈ°λŠ₯을 μ œκ³΅ν•˜λ©°, HTTP response 검증과 κ΄‘λ²”μœ„ν•œ Unit Test, 톡합 Test 등을 μ§€μ›ν•©λ‹ˆλ‹€

completionHandler 의 escaping closure μ„ μ–Έ 이유

  • func μ—μ„œ escape 선언은 ν•¨μˆ˜μ˜ scope λ₯Ό λ²—μ–΄ λ‚˜μ„œλ„ λ³€μˆ˜κ°€ μ°Έμ‘° 될 수 있게 ν•˜λŠ” 클둜져 μž„. 즉, ν•¨μˆ˜μ˜ 인자둜 closure κ°€ μ „λ‹¬λ˜μ§€λ§Œ, λ°˜ν™˜λœ 후에도 μ‹€ν–‰λ˜λŠ” 것을 μ˜λ―Έν•©λ‹ˆλ‹€.

  • escaping closure λ₯Ό μ‚¬μš©ν•˜λŠ” λŒ€ν‘œμ μΈ κ²½μš°λŠ” 비동기 μž‘μ—…μ„ ν•˜λŠ” 경우 completionHandler λ‘œμ„œ escaping closure λ₯Ό 많이 μ‚¬μš©ν•©λ‹ˆλ‹€. 보톡 λ„€νŠΈμ›Œν‚Ή 톡신은 비동기 μž‘μ—…μœΌλ‘œ 처리 λ˜λŠ”λ°, .responseData 에 μ •μ˜λœ completionHandler closure λŠ” fetch data κ°€ λ°˜ν™˜ 된 후에, 호좜이 λ©λ‹ˆλ‹€. μ™œλƒν•˜λ©΄, μ„œλ²„μ—μ„œ 데이터λ₯Ό μ–Έμ œ 응닡 해쀄지 λͺ¨λ₯΄κ³ , μ‘λ‹΅μ‹œκ°„μ΄ λ‘œλ”© 되기 λ•Œλ¬Έμ— server μ—μ„œ λΉ„λ™κΈ°λ‘œ 응닡 λ°›κΈ° 전에 즉, .responseData 에 μ „λ‹¬ν•œ parameter κ°€ completionHandlerκ°€ 호좜되기 전에 ν•¨μˆ˜κ°€ μ’…λ£Œλ˜μ„œ μ„œλ²„μ˜ 응닡을 받아도 λ™μž‘ν•˜μ§€ μ•Šκ²Œ λ©λ‹ˆλ‹€

  • κ·Έλž˜μ„œ, 비동기 μž‘μ—…μ„ completionHandler 둜 callback 을 μ‹œμΌœμ€˜μ•Ό ν•œλ‹€λ©΄, escaping closure λ₯Ό μ‚¬μš©ν•˜μ—¬ ν•¨μˆ˜κ°€ return 된 후에도, μ‹€ν–‰ μ‹œμΌœμ€˜μ•Ό ν•©λ‹ˆλ‹€

// in viewDidLoad.swift

	// fetch data SearchCovideOverview
	func fetchCovidOverview(
		// API λ₯Ό ν†΅ν•΄μ„œ severμ—μ„œ json dat λ₯Ό λ°›κ±°λ‚˜, μš”μ²­μ— μ‹€νŒ¨ ν•˜μ˜€μ„λ•Œ completionHandler λ₯Ό ν˜ΈμΆœν•΄μ„œ ν•΄λ‹Ή closure λ₯Ό μ •μ˜ν•˜λŠ” 곳에 응닡받은 dataλ₯Ό 전달 ν•΄μ•Ό ν•©λ‹ˆλ‹€
		// completionHandler λ₯Ό @escaping closure κ°€ 되게 μ„€μ •
		completionHandler: @escaping (Result<CityCovidOverView, Error>) -> Void
	) {
		let url = "https://api.corona-19.kr/korea/country/new/"
		let param = [
			"serviceKey": "16KIXAdhg7tk93ivjzsHFCQ8oOLyNSUuE"
		]

		// Alamofire λ₯Ό ν†΅ν•΄μ„œ API 호좜
		AF.request(url, method: .get, parameters: param)
			.responseData(completionHandler: { response in
				switch response.result {
				case let .success(data):
					do {
						let decoder = JSONDecoder()
						let result = try decoder.decode(CityCovidOverView.self, from: data)
						completionHandler(.success(result))
					} catch { // error code 처리
						completionHandler(.failure(error))
					}
				case let .failure(error):
					completionHandler(.failure(error))
				}
			})
	}

πŸ”· Cocoapods

  • Apple platform μ—μ„œ κ°œλ°œμ„ ν•  λ•Œ, μ™ΈλΆ€ 라이브λ₯Ό κ΄€λ¦¬ν•˜κΈ° 쉽도둝 λ„μ™€μ£ΌλŠ” μ˜μ‘΄μ„± 관리도ꡬ μž…λ‹ˆλ‹€

  • ν”„λ‘œμ νŠΈμ—μ„œ ν•„μš”ν•œ μ™ΈλΆ€ 라이브러리λ₯Ό μ‰½κ²Œ κ΄€λ¦¬ν•˜κ³ , μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Cocoapods official site - https://cocoapods.org/

Cocoapods μ„€μΉ˜

$ sudo gem install cocoapods

Cocoapods ν”„λ‘œμ νŠΈμ— 적용

  • xcode 둜 μƒˆλ‘œμš΄ project λ₯Ό μƒμ„±ν•˜λ©΄ κ·Έ κ²½λ‘œμ— terminal 둜 κ°€μ„œ Podfile 생성
pod init
  • Podfile 을 μˆ˜μ •ν•˜κ²Œ 되면 μ™ΈλΆ€ 라이브러리λ₯Ό κ°€μ Έμ˜€κ±°λ‚˜, μˆ˜μ • ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

πŸ”· Loading indicator

  • ViewController 에 loading indicator λ₯Ό ν‘œμ‹œν•˜μ—¬, Covid API λ₯Ό 호좜 ν•˜μ˜€μ„ λ•Œ, μ„œλ²„μ—μ„œ 응닡이 였기 전이라면 화면에 indicator κ°€ ν‘œμ‹œλ˜κ²Œ κ΅¬ν˜„ν•˜κΈ°

  • μ„œλ²„μ—μ„œ 응닡이 μ˜¨λ‹€λ©΄, indicator λ₯Ό 숨기고 label κ³Ό pieChart κ°€ ν‘œμ‹œλ˜κ²Œ κ΅¬ν˜„ ν•˜κΈ°

κ΅¬ν˜„ 방법

  • storyboard μ—μ„œ Activity Indicator μΆ”κ°€ ν•œλ‹€μŒμ— 기쑴에 StackView의 label, pieChartView μ—λŠ” hidden 을 체크 ν•΄μ€˜μ„œ μž μ‹œ μˆ¨κΉ€λ‹ˆλ‹€
// in ViewController.swift

	override func viewDidLoad() {
		super.viewDidLoad()
		// app 이 μ‹€ν–‰λ˜λ©΄ indicator 의 animation μ‹œμž‘
		self.indicatorView.startAnimating()
		// μˆœν™˜μ°Έμ‘°λ₯Ό λ°©μ§€ν•˜κΈ° μœ„ν•΄μ„œ [weak self] 둜 capture list λ₯Ό μ •μ˜ν•΄μ€Œ
		self.fetchCovidOverview(completionHandler: { [weak self] result in
			guard let self = self else { return } // self κ°€ μΌμ‹œμ μœΌλ‘œ strong 이 되게 함
			// 응닡이 였면 completionHandler κ°€ μž‘λ™λ˜κΈ° λ•Œλ¬Έμ— μ΄λ•Œ indicatorView 의 animating 을 stop μ‹œμΌœ μ£Όκ³ , hidden μ‹œμΌœ μ£Όκ³ , λ‚˜λ¨Έμ§€ information data 뢀뢄이 λ‚˜νƒ€λ‚˜κ²Œ ν•΄μ€Œ
			self.indicatorView.stopAnimating()
			self.indicatorView.isHidden = true
			self.labelStackView.isHidden = false
			self.readingDate.isHidden = false
			self.pieChartView.isHidden = false
  ......
    }
  }

πŸ”· API Key 숨기기

  • GitHub λ‚˜ μ™ΈλΆ€λ‘œ public ν•˜κ²Œ project κ³΅μœ μ‹œ, apiKey λ‚˜, passWord, authentication κ΄€λ ¨ key 값듀을 외뢀에 λ…ΈμΆœ μ‹œν‚€μ§€ μ•ŠκΈ° μœ„ν•΄μ„œ code 에 key 값을 λ°”λ‘œ μ λŠ”κ²ƒμ΄ μ•„λ‹ˆλΌ, plist (property list) λ₯Ό μƒμ„±ν•΄μ€˜μ„œ λ”°λ‘œ 관리 ν•΄μ•Ό ν•©λ‹ˆλ‹€

1. API_KEY λ₯Ό μ €μž₯ν•  plist 생성

  • Key κ°’μœΌλ‘œ API_KEY value κ°’μœΌλ‘œ API key 값을 λ„£μŠ΅λ‹ˆλ‹€

image

2. key 값을 뢈러올 Extension 파일 생성

// in CovidApp++Bundle.swift
// "앱이름++Bundle.swift ν˜•μ‹μœΌλ‘œ

import Foundation

// Bundle κ°’μœΌλ‘œ λ³€μˆ˜ key λ₯Ό return
extension Bundle {
	var apiKey: String {
		guard let file = self.path(forResource: "CovidKey", ofType: "plist") else { return ""}

		guard let resource = NSDictionary(contentsOfFile: file) else {return ""}
		guard let key = resource["API_KEY"] as? String else { fatalError("Check API Key value")}
		return key
	}
}

πŸ“Œ Bundle 에 extension ν•΄μ„œ μž‘μ„±ν•˜λŠ” 이유?

  • Bundle μ΄λž€ μ‹€ν–‰κ°€λŠ₯ν•œ μ½”λ“œμ™€ κ·Έ μ½”λ“œμ˜ μžμ›μ„ ν¬ν•¨ν•˜κ³  μžˆλŠ” 디렉토리 μž…λ‹ˆλ‹€.

  • Bundle μ•ˆμ— apiKey 값을 κ°€μ Έμ˜€κΈ° μœ„ν•΄ Bundle.main.apiKey 순으둜 μ ‘κ·Όν•΄μ„œ μ‚¬μš©ν•©λ‹ˆλ‹€

3. API 호좜 ν• λ•Œ plist 에 μ €μž₯ν•œ API_KEY 정보 λΆˆλŸ¬μ™€ λŒ€μž…ν•˜κΈ°

// in viewController.swift

// fetch data SearchCovideOverview
func fetchCovidOverview(
	// API λ₯Ό ν†΅ν•΄μ„œ severμ—μ„œ json dat λ₯Ό λ°›κ±°λ‚˜, μš”μ²­μ— μ‹€νŒ¨ ν•˜μ˜€μ„λ•Œ completionHandler λ₯Ό ν˜ΈμΆœν•΄μ„œ ν•΄λ‹Ή closure λ₯Ό μ •μ˜ν•˜λŠ” 곳에 응닡받은 dataλ₯Ό 전달 ν•΄μ•Ό ν•©λ‹ˆλ‹€
	// completionHandler λ₯Ό @escaping closure κ°€ 되게 μ„€μ •
	completionHandler: @escaping (Result<CityCovidOverView, Error>) -> Void
) {
	let apiKey = Bundle.main.apiKey
	let url = "https://api.corona-19.kr/korea/country/new/"
	let param = [
		"serviceKey": apiKey
	]
....

4. .gitignore 에 μΆ”κ°€ μ‹œν‚€κΈ°

# Created by https://www.toptal.com/developers/gitignore/api/xcode,cocoapods
# Edit at https://www.toptal.com/developers/gitignore?templates=xcode,cocoapods

### CocoaPods ###
## CocoaPods GitIgnore Template

# CocoaPods - Only use to conserve bandwidth / Save time on Pushing
#           - Also handy if you have a large number of dependant pods
#           - AS PER https://guides.cocoapods.org/using/using-cocoapods.html NEVER IGNORE THE LOCK FILE
Pods/


### Xcode ###
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore

##APIKEY
CovidKey.plist

## User settings
xcuserdata

.....

5. Git 좔적 쀑지 μ‹œν‚€κΈ°

  • μΆ”ν›„ git clone project μ‹€ν–‰μ‹œ local ν™˜κ²½μ—μ„œ APIKEY 값이 λ³€κ²½λ˜λ”λΌλ„ git μ—μ„œ μžλ™ μΆ”μ λ˜μ§€ μ•Šκ³  gitHub 등에 μ—…λ‘œλ“œ λ˜μ§€ μ•Šκ²Œ ν•˜κΈ°μž…λ‹ˆλ‹€
# git update-index --skip-worktree  ν”„λ‘œμ νŠΈλͺ…/파일λͺ….plist
git update-index --skip-worktree  07_covid_app/covidKey.plist
  • λ‹€μ‹œ 원상 λ³΅κ·€λŠ” --no-skip ν•΄μ£Όλ©΄ λ©λ‹ˆλ‹€
git update-index --no-skip-worktree  07_covid_app/covidKey.plist

Describing check point in details in Jacob's DevLog - https://jacobko.info/ios/ios-08/


πŸ”Ά πŸ”· πŸ“Œ πŸ”‘ πŸ‘‰

πŸ—ƒ Reference

Jacob's DevLog - https://jacobko.info/uikit/ios-08/

λ‚˜λ₯Έν•œ μ½”λ”© - https://nareunhagae.tistory.com/44

codewithchrist - https://codewithchris.com/alamofire/

fastcampus - https://fastcampus.co.kr/dev_online_iosappfinal

About

To practice alamofire, cocoapods and charts library

https://jacobko.info/uikit/ios-08/


Languages

Language:Swift 98.1%Language:Ruby 1.9%