[iOS 앱개발 초격차 패키지] Part 2. 코로나 현황판 앱 만들기
코로나 현황판 앱
Intro
[기능 설명]
→ 시도별 신규 확진자 수가 파이 차트로 표시됨
→ 도시 항목을 선택하면 상세 현황을 볼 수 있는 화면으로 이동됨
[활용할 기술들]
→ 굿바이 코로나 19 API
→ Alamofire
→ Cocoapods
Alamofire
- Swift 기반의 HTTP 네트워킹 라이브러리
- Alamofire의 주요 특징
→ 연결 가능한 request, response 메소드를 제공
→ URL, JSON 형태의 파라미터 인코딩을 지원
→ 파일 데이터 스트링, 멀티 파트 폼 데이터 등의 업로드 기능을 제공
→ HTTP response의 검증과 광범위한 단위 테스트 및 통합 테스트를 제공 - URLSession 대신 Alamofire를 사용하는 이유
→ 코드의 간소화, 가독성 측면에서 도움을 주고 여러 기능을 직접 구축하지 않아도 쉽게 사용할 수 있음
굿바이 코로나19 API
CocoaPods
- 애플 플랫폼에서 개발할 때 외부 라이브러리를 관리하기 쉽도록 도와주는 의존성 관리 도구
- 설치 방법(터미널)
→ $ sudo gem install cocoapods
→ 프로젝트 경로로 이동하여 pod init을 입력
→ podfile이 생성되는데, 이 파일을 수정하여 외부 라이브러리를 사용할 수 있음
→ 아래와 같이 외부 라이브러리를 입력해준 뒤 터미널에서 pod install 명령어를 사용하여 라이브러리 설치
기능 구현(코드)
//
// ViewController.swift
// COVID19
//
// Created by TAEJANIM on 2021/11/24.
//
import UIKit
import Alamofire
import Charts
class ViewController: UIViewController {
@IBOutlet weak var totalCaseLabel: UILabel!
@IBOutlet weak var newCaseLabel: UILabel!
@IBOutlet weak var pieChartView: PieChartView!
@IBOutlet weak var labelStackView: UIStackView!
@IBOutlet weak var indicatorView: UIActivityIndicatorView!
override func viewDidLoad() {
super.viewDidLoad()
self.indicatorView.startAnimating()
self.fetchCovidOverview(completionHandler: { [weak self] result in
guard let self = self else { return }
self.indicatorView.stopAnimating()
self.indicatorView.isHidden = true
self.labelStackView.isHidden = false
self.pieChartView.isHidden = false
switch result {
case let .success(result):
self.configureStackView(koreaCovidOverview: result.korea)
let covidOverviewList = self.makeCovidOverviewList(cityCovidOVerview: result)
self.configureChartView(covidOverviewList: covidOverviewList)
case let .failure(error):
debugPrint("error \(error)")
}
})
}
func makeCovidOverviewList(
cityCovidOVerview: CityCovidOverview
) -> [CovidOverview] {
return [
cityCovidOVerview.seoul,
cityCovidOVerview.busan,
cityCovidOVerview.daegu,
cityCovidOVerview.incheon,
cityCovidOVerview.gwangju,
cityCovidOVerview.daejeon,
cityCovidOVerview.ulsan,
cityCovidOVerview.sejong,
cityCovidOVerview.gyeonggi,
cityCovidOVerview.chungbuk,
cityCovidOVerview.chungnam,
cityCovidOVerview.gyeongbuk,
cityCovidOVerview.gyeongnam,
cityCovidOVerview.jeju
]
}
func configureChartView(covidOverviewList: [CovidOverview]) {
self.pieChartView.delegate = self
let entries = covidOverviewList.compactMap { [weak self] overview -> PieChartDataEntry? in
guard let self = self else { return nil }
return PieChartDataEntry(
value: self.removeFormatString(string: overview.newCase),
label: overview.countryName,
data: overview
)
}
let dataSet = PieChartDataSet(entries: entries, label: "코로나 발생 현황")
dataSet.sliceSpace = 1
dataSet.entryLabelColor = .black
dataSet.valueTextColor = .black
dataSet.xValuePosition = .outsideSlice
dataSet.valueLinePart1OffsetPercentage = 0.8
dataSet.valueLinePart1Length = 0.2
dataSet.valueLinePart2Length = 0.3
dataSet.colors = ChartColorTemplates.vordiplom() +
ChartColorTemplates.joyful() +
ChartColorTemplates.liberty() +
ChartColorTemplates.pastel() +
ChartColorTemplates.material()
self.pieChartView.data = PieChartData(dataSet: dataSet)
self.pieChartView.spin(duration: 0.3, fromAngle: self.pieChartView.rotationAngle, toAngle: self.pieChartView.rotationAngle + 80)
}
func removeFormatString(string: String) -> Double {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
return formatter.number(from: string)?.doubleValue ?? 0
}
func configureStackView(koreaCovidOverview: CovidOverview) {
self.totalCaseLabel.text = "\(koreaCovidOverview.totalCase)명"
self.newCaseLabel.text = "\(koreaCovidOverview.newCase)명"
}
func fetchCovidOverview(
completionHandler: @escaping (Result<CityCovidOverview, Error>) -> Void
) {
let url = "https://api.corona-19.kr/korea/country/new/"
let param = [
"serviceKey": "s9ntxCvVBUq83ZlJaNdpPzo4Gr2bjTh5E"
]
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 {
completionHandler(.failure(error))
}
case let .failure(error):
completionHandler(.failure(error))
}
})
}
}
extension ViewController: ChartViewDelegate {
func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {
guard let covidDetailViewController = self.storyboard?.instantiateViewController(withIdentifier: "CovidDetailViewController") as? CovidDetailViewController else { return }
guard let covidOverview = entry.data as? CovidOverview else { return }
covidDetailViewController.covidOverview = covidOverview
self.navigationController?.pushViewController(covidDetailViewController, animated: true)
}
}
//
// CityCovidOverview.swift
// COVID19
//
// Created by TAEJANIM on 2021/11/30.
//
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
}
//
// CovidDetailViewController.swift
// COVID19
//
// Created by TAEJANIM on 2021/11/30.
//
import UIKit
class CovidDetailViewController: UITableViewController {
@IBOutlet weak var newCaseCell: UITableViewCell!
@IBOutlet weak var totalCaseCell: UITableViewCell!
@IBOutlet weak var recoveredCell: UITableViewCell!
@IBOutlet weak var deathCell: UITableViewCell!
@IBOutlet weak var percentageCell: UITableViewCell!
@IBOutlet weak var overseasInflowCell: UITableViewCell!
@IBOutlet weak var regionalOutbreakCell: UITableViewCell!
var covidOverview: CovidOverview?
override func viewDidLoad() {
super.viewDidLoad()
self.configureView()
}
func configureView() {
guard let covidOverview = self.covidOverview else { return }
self.title = covidOverview.countryName
self.newCaseCell.detailTextLabel?.text = "\(covidOverview.newCase)명"
self.totalCaseCell.detailTextLabel?.text = "\(covidOverview.totalCase)명"
self.recoveredCell.detailTextLabel?.text = "\(covidOverview.recovered)명"
self.deathCell.detailTextLabel?.text = "\(covidOverview.death)명"
self.percentageCell.detailTextLabel?.text = "\(covidOverview.percentage)%"
self.overseasInflowCell.detailTextLabel?.text = "\(covidOverview.newFcase)명"
self.regionalOutbreakCell.detailTextLabel?.text = "\(covidOverview.newCcase)명"
}
}
Outro
- Alamofire
→ Swift 기반의 HTTP 네트워킹 라이브러리
→ URL session에 기반한 라이브러리로, 네트워킹 작업을 단순화하고 네트워킹을 위한 다양한 메소드와 JSON 파싱 등을 제공함
→ URL session과 비교했을 때 코드의 간소함이 가독성 측면에서 도움을 주고, 여러 기능을 직접 구축하지 않고 쉽게 사용할 수 있음
→ 이번 프로젝트에서는 Alamofire의 Request 메소드를 이용하여 굿바이 코로나 API를 호출했고, response data 메소드를 체이닝하여 서버에서 응답받은 데이터를 받아올 수 있도록 구현하였음 - Cocoapods
→ 애플 플랫폼에서 개발할 때 외부 라이브러리를 관리하는 것이 쉽도록 도와주는 의존성 관리 도구
→ Alamofire와 Charts 라이브러리를 사용하기 위해 cocoapods을 사용했음
결과물
Author And Source
이 문제에 관하여([iOS 앱개발 초격차 패키지] Part 2. 코로나 현황판 앱 만들기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@taejanim/iOS-앱개발-초격차-패키지-Part-2.-코로나-현황판-앱-만들기저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)