第13部:CoreLocationと完全な注釈付きコード(復習)を使用する
settings
Privacy> Location services> app
デバッグ>Location>シミュレータの位置の決定方法
ここで変更した後、変更した値を決定するには、アプリケーションを削除して再実行する必要があります.
.plist
Property List
すべてのXcodeプロジェクトで自動生成
アプリケーション実行時の設定情報(アプリケーション実行時)を含む
key-valuepairとして値を格納
key: property name
value: configuration
Setting a property
Change reflected in plist
ロケーションマネージャを使用する場合
権限要求メッセージの送信時に追加する必要があります
+キーを押して「ユーザー使用状況」Descriptionを選択し、Valueにコメントを書く
https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/AboutInformationPropertyListFiles.html
// ViewController.swift
import CoreLocation
class WeatherViewController: UIViewController {
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
// 위치 요청 전에 미리 위임해야 한다
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.requestLocation() //one-time 한 번만 call
}
@IBAction func locationPressed(_ sender: Any) {
locationManager.requestLocation()
}
}
//MARK: - CLLocationManagerDelegate
extension WeatherViewController: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.last {
locationManager.stopUpdatingLocation() //로케이션매니저 종료하기
let lat = location.coordinate.latitude
let lon = location.coordinate.longitude
weatherManager.fetchWeather(latitude: lat, longitute: lon)
}
}
// 조건에 따라 에러 메서드(아래)도 반드시 구현해야 한다
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(error)
}
}
// WeatherManager.swift
func fetchWeather(latitude: CLLocationDegrees, longitude: CLLocationDegrees) {
let urlString = "\(weatherURL)&lat=\(latitude)&lon=\(longitude)"
performRequest(with: urlString)
}
コメント付き完全コード // WeatherViewController.swift
import UIKit
import CoreLocation
class WeatherViewController: UIViewController {
@IBOutlet weak var conditionImageView: UIImageView!
@IBOutlet weak var temperatureLabel: UILabel!
@IBOutlet weak var cityLabel: UILabel!
@IBOutlet weak var searchTextField: UITextField!
@IBOutlet weak var currentLocation: UIButton!
var weatherManager = WeatherManager()
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
// 위치 요청 전에 미리 위임해야 한다
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.requestLocation() //one-time 한 번만
//locationManager.startUpdatingLocation() //내비게이션처럼 이동하는 정보를 계속 수집
// WeatherViewController가 weatherManager를 위임한다
weatherManager.delegate = self
searchTextField.delegate = self
}
@IBAction func locationPressed(_ sender: UIButton) {
locationManager.requestLocation()
}
}
//MARK: - UITextFieldDelegate, WeatherManagerDelegate
extension WeatherViewController: UITextFieldDelegate {
@IBAction func searchPressed(_ sender: UIButton) {
//키보드 해제
searchTextField.endEditing(true)
print(searchTextField.text!)
}
// should가 들어가면 bool을 return받아서 행동을 정한다
// return(Go)를 눌렀을 때
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
searchTextField.endEditing(true)
print(searchTextField.text!)
return true
}
// 유효성 검사
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
// 아무것도 없으면 멈추고, 아니면 Type something 보여주기
if textField.text != "" {
return true
} else {
textField.placeholder = "Type something"
return false
}
}
// 텍스트 필드에 글자 입력 후 return이나 버튼을 눌러 입력한 후
// 키보드를 해제했을 때 텍스트 필드 공백으로 만들기
func textFieldDidEndEditing(_ textField: UITextField) {
if let city = searchTextField.text {
weatherManager.fetchWeather(cityName: city)
}
searchTextField.text = ""
}
}
//MARK: - WeatherManagerDelegate
extension WeatherViewController: WeatherManagerDelegate {
// delegate method의 parameter규칙
// argument(밖에서 호출), parameter(안에서 사용, external과 internal이 있음)
// delegate method를 생성시킨 data type WeatherManager를 앞에 써주고 external parameter는 생략표시(_) 한다
func didUpdateWeather(_ weatherManager: WeatherManager, weather: WeatherModel) {
// 클로저 안에서는 self를 써준다
DispatchQueue.main.async {
self.temperatureLabel.text = weather.temperatureString
self.conditionImageView.image = UIImage(systemName: weather.conditionName)
self.cityLabel.text = weather.cityName
}
}
func didFailWithError(error: Error) {
print(error)
}
}
//MARK: - CLLocationManagerDelegate
extension WeatherViewController: CLLocationManagerDelegate {
//CL core Location
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.last {
locationManager.stopUpdatingLocation()
let lat = location.coordinate.latitude
let lon = location.coordinate.longitude
weatherManager.fetchWeather(latitude: lat, longitude: lon)
}
}
// 조건에 따라 에러 메서드(아래)도 반드시 구현해야 한다
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(error)
}
}
WeatherManager.swift//
// WeatherManager.swift
// Clima
//
// Created by Etoday on 2021/02/15.
// Copyright © 2021 App Brewery. All rights reserved.
//
import Foundation
import CoreLocation
protocol WeatherManagerDelegate {
func didUpdateWeather(_ weatherManager: WeatherManager, weather: WeatherModel)
func didFailWithError(error: Error)
}
struct WeatherManager {
let weatherURL = "https://api.openweathermap.org/data/2.5/weather?appid=42250e4b3738d98ef5dae4a4635b68fd&units=metric"
var delegate: WeatherManagerDelegate?
func fetchWeather(cityName: String) {
let urlString = "\(weatherURL)&q=\(cityName)"
performRequest(with: urlString)
}
func fetchWeather(latitude: CLLocationDegrees, longitude: CLLocationDegrees) {
let urlString = "\(weatherURL)&lat=\(latitude)&lon=\(longitude)"
performRequest(with: urlString)
}
func performRequest(with urlString: String) {
//1. Create a URL
if let url = URL(string: urlString) {
// 2. Create a URLSession 기본 설정(브라우저)
let session = URLSession(configuration: .default)
// 3. Give the session a task
let task = session.dataTask(with: url) { (data, response, error) in
// 에러 처리
if error != nil {
self.delegate?.didFailWithError(error: error!)
return // exit
}
// parse into JSON format 파싱해서 delegate를 활용해서 WeatherViewController에 띄우기
if let safeData = data {
// 클로저 안에서 메서드를 호출할 때는 self를 써줘야 한다
// 파싱이 성공했을 때 delegate가 있으면 didUpdateWeather를 실행시킨다
if let weather = self.parseJSON(safeData) {
self.delegate?.didUpdateWeather(self, weather: weather)
}
}
}
// 4. Start the task
task.resume()
}
}
func parseJSON(_ weatherData: Data) -> WeatherModel? {
let decoder = JSONDecoder()
// input으로 object가 아니라 type을 받는데, .self를 붙여 type object의 참조값을 사용한다
// WeatherData structure을 사용해 decode를 시도한다
do {
let decodedData = try decoder.decode(WeatherData.self, from: weatherData)
let id = decodedData.weather[0].id
let temp = decodedData.main.temp
let name = decodedData.name
let weather = WeatherModel(conditionId: id, cityName: name, temperature: temp)
return weather
} catch {
delegate?.didFailWithError(error: error)
return nil
}
}
}
WeatherData.swift//
// WeatherData.swift
// Clima
// 여기는 JSON Parsing하기 위한 곳
// Created by Etoday on 2021/02/15.
// Copyright © 2021 App Brewery. All rights reserved.
//
import Foundation
//Decodable+Encodable -> Codable
struct WeatherData: Codable {
let name: String
// JSON의 일부분 (예시)
// main안에는 object{}가 들어있음
// "main": {
// "temp": 23.48,
// "pressure": 1024,
// "humidity": 40,
// "temp_min": 21,
// "temp_max": 25
// }
let main: Main
// weather안에는 [] 배열이 들어있음
// "weather": [
// {
// "id": 803,
// "main": "Clouds",
// "description": "broken clouds",
// "icon": "04n"
// }
// ]
let weather: [Weather]
}
// 변수명이 JSON의 변수명과 정확히 일치해야 한다
struct Main: Codable {
let temp: Double
}
struct Weather: Codable {
let description: String
let id: Int
}
WeatherModel.swift//
// WeatherModel.swift
// Clima
// 여기는 화면에 보여줄 데이터를 계산하기 위한 곳
// Created by Etoday on 2021/02/15.
// Copyright © 2021 App Brewery. All rights reserved.
//
import Foundation
struct WeatherModel {
//stored property
public let conditionId: Int
public let cityName: String
public let temperature: Double
public var temperatureString: String {
return String(format: "%.1f", temperature)
}
//computed property (var 사용)
var conditionName: String {
switch conditionId {
case 200...232:
return "cloud.bolt"
case 300...321:
return "cloud.drizzle"
case 500...531:
return "cloud.rain"
case 600...622:
return "cloud.snow"
case 701...781:
return "cloud.fog"
case 800:
return "sun.max"
case 801...804:
return "cloud.bolt"
default:
return "cloud"
}
}
}
Reference
この問題について(第13部:CoreLocationと完全な注釈付きコード(復習)を使用する), 我々は、より多くの情報をここで見つけました
https://velog.io/@msi753/Udemy-iOS-섹션13-코드-주석
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
Property List
すべてのXcodeプロジェクトで自動生成
アプリケーション実行時の設定情報(アプリケーション実行時)を含む
key-valuepairとして値を格納
key: property name
value: configuration
Setting a property
Change reflected in plist
ロケーションマネージャを使用する場合
権限要求メッセージの送信時に追加する必要があります
+キーを押して「ユーザー使用状況」Descriptionを選択し、Valueにコメントを書く
https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/AboutInformationPropertyListFiles.html
// ViewController.swift
import CoreLocation
class WeatherViewController: UIViewController {
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
// 위치 요청 전에 미리 위임해야 한다
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.requestLocation() //one-time 한 번만 call
}
@IBAction func locationPressed(_ sender: Any) {
locationManager.requestLocation()
}
}
//MARK: - CLLocationManagerDelegate
extension WeatherViewController: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.last {
locationManager.stopUpdatingLocation() //로케이션매니저 종료하기
let lat = location.coordinate.latitude
let lon = location.coordinate.longitude
weatherManager.fetchWeather(latitude: lat, longitute: lon)
}
}
// 조건에 따라 에러 메서드(아래)도 반드시 구현해야 한다
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(error)
}
}
// WeatherManager.swift
func fetchWeather(latitude: CLLocationDegrees, longitude: CLLocationDegrees) {
let urlString = "\(weatherURL)&lat=\(latitude)&lon=\(longitude)"
performRequest(with: urlString)
}
コメント付き完全コード // WeatherViewController.swift
import UIKit
import CoreLocation
class WeatherViewController: UIViewController {
@IBOutlet weak var conditionImageView: UIImageView!
@IBOutlet weak var temperatureLabel: UILabel!
@IBOutlet weak var cityLabel: UILabel!
@IBOutlet weak var searchTextField: UITextField!
@IBOutlet weak var currentLocation: UIButton!
var weatherManager = WeatherManager()
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
// 위치 요청 전에 미리 위임해야 한다
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.requestLocation() //one-time 한 번만
//locationManager.startUpdatingLocation() //내비게이션처럼 이동하는 정보를 계속 수집
// WeatherViewController가 weatherManager를 위임한다
weatherManager.delegate = self
searchTextField.delegate = self
}
@IBAction func locationPressed(_ sender: UIButton) {
locationManager.requestLocation()
}
}
//MARK: - UITextFieldDelegate, WeatherManagerDelegate
extension WeatherViewController: UITextFieldDelegate {
@IBAction func searchPressed(_ sender: UIButton) {
//키보드 해제
searchTextField.endEditing(true)
print(searchTextField.text!)
}
// should가 들어가면 bool을 return받아서 행동을 정한다
// return(Go)를 눌렀을 때
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
searchTextField.endEditing(true)
print(searchTextField.text!)
return true
}
// 유효성 검사
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
// 아무것도 없으면 멈추고, 아니면 Type something 보여주기
if textField.text != "" {
return true
} else {
textField.placeholder = "Type something"
return false
}
}
// 텍스트 필드에 글자 입력 후 return이나 버튼을 눌러 입력한 후
// 키보드를 해제했을 때 텍스트 필드 공백으로 만들기
func textFieldDidEndEditing(_ textField: UITextField) {
if let city = searchTextField.text {
weatherManager.fetchWeather(cityName: city)
}
searchTextField.text = ""
}
}
//MARK: - WeatherManagerDelegate
extension WeatherViewController: WeatherManagerDelegate {
// delegate method의 parameter규칙
// argument(밖에서 호출), parameter(안에서 사용, external과 internal이 있음)
// delegate method를 생성시킨 data type WeatherManager를 앞에 써주고 external parameter는 생략표시(_) 한다
func didUpdateWeather(_ weatherManager: WeatherManager, weather: WeatherModel) {
// 클로저 안에서는 self를 써준다
DispatchQueue.main.async {
self.temperatureLabel.text = weather.temperatureString
self.conditionImageView.image = UIImage(systemName: weather.conditionName)
self.cityLabel.text = weather.cityName
}
}
func didFailWithError(error: Error) {
print(error)
}
}
//MARK: - CLLocationManagerDelegate
extension WeatherViewController: CLLocationManagerDelegate {
//CL core Location
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.last {
locationManager.stopUpdatingLocation()
let lat = location.coordinate.latitude
let lon = location.coordinate.longitude
weatherManager.fetchWeather(latitude: lat, longitude: lon)
}
}
// 조건에 따라 에러 메서드(아래)도 반드시 구현해야 한다
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(error)
}
}
WeatherManager.swift//
// WeatherManager.swift
// Clima
//
// Created by Etoday on 2021/02/15.
// Copyright © 2021 App Brewery. All rights reserved.
//
import Foundation
import CoreLocation
protocol WeatherManagerDelegate {
func didUpdateWeather(_ weatherManager: WeatherManager, weather: WeatherModel)
func didFailWithError(error: Error)
}
struct WeatherManager {
let weatherURL = "https://api.openweathermap.org/data/2.5/weather?appid=42250e4b3738d98ef5dae4a4635b68fd&units=metric"
var delegate: WeatherManagerDelegate?
func fetchWeather(cityName: String) {
let urlString = "\(weatherURL)&q=\(cityName)"
performRequest(with: urlString)
}
func fetchWeather(latitude: CLLocationDegrees, longitude: CLLocationDegrees) {
let urlString = "\(weatherURL)&lat=\(latitude)&lon=\(longitude)"
performRequest(with: urlString)
}
func performRequest(with urlString: String) {
//1. Create a URL
if let url = URL(string: urlString) {
// 2. Create a URLSession 기본 설정(브라우저)
let session = URLSession(configuration: .default)
// 3. Give the session a task
let task = session.dataTask(with: url) { (data, response, error) in
// 에러 처리
if error != nil {
self.delegate?.didFailWithError(error: error!)
return // exit
}
// parse into JSON format 파싱해서 delegate를 활용해서 WeatherViewController에 띄우기
if let safeData = data {
// 클로저 안에서 메서드를 호출할 때는 self를 써줘야 한다
// 파싱이 성공했을 때 delegate가 있으면 didUpdateWeather를 실행시킨다
if let weather = self.parseJSON(safeData) {
self.delegate?.didUpdateWeather(self, weather: weather)
}
}
}
// 4. Start the task
task.resume()
}
}
func parseJSON(_ weatherData: Data) -> WeatherModel? {
let decoder = JSONDecoder()
// input으로 object가 아니라 type을 받는데, .self를 붙여 type object의 참조값을 사용한다
// WeatherData structure을 사용해 decode를 시도한다
do {
let decodedData = try decoder.decode(WeatherData.self, from: weatherData)
let id = decodedData.weather[0].id
let temp = decodedData.main.temp
let name = decodedData.name
let weather = WeatherModel(conditionId: id, cityName: name, temperature: temp)
return weather
} catch {
delegate?.didFailWithError(error: error)
return nil
}
}
}
WeatherData.swift//
// WeatherData.swift
// Clima
// 여기는 JSON Parsing하기 위한 곳
// Created by Etoday on 2021/02/15.
// Copyright © 2021 App Brewery. All rights reserved.
//
import Foundation
//Decodable+Encodable -> Codable
struct WeatherData: Codable {
let name: String
// JSON의 일부분 (예시)
// main안에는 object{}가 들어있음
// "main": {
// "temp": 23.48,
// "pressure": 1024,
// "humidity": 40,
// "temp_min": 21,
// "temp_max": 25
// }
let main: Main
// weather안에는 [] 배열이 들어있음
// "weather": [
// {
// "id": 803,
// "main": "Clouds",
// "description": "broken clouds",
// "icon": "04n"
// }
// ]
let weather: [Weather]
}
// 변수명이 JSON의 변수명과 정확히 일치해야 한다
struct Main: Codable {
let temp: Double
}
struct Weather: Codable {
let description: String
let id: Int
}
WeatherModel.swift//
// WeatherModel.swift
// Clima
// 여기는 화면에 보여줄 데이터를 계산하기 위한 곳
// Created by Etoday on 2021/02/15.
// Copyright © 2021 App Brewery. All rights reserved.
//
import Foundation
struct WeatherModel {
//stored property
public let conditionId: Int
public let cityName: String
public let temperature: Double
public var temperatureString: String {
return String(format: "%.1f", temperature)
}
//computed property (var 사용)
var conditionName: String {
switch conditionId {
case 200...232:
return "cloud.bolt"
case 300...321:
return "cloud.drizzle"
case 500...531:
return "cloud.rain"
case 600...622:
return "cloud.snow"
case 701...781:
return "cloud.fog"
case 800:
return "sun.max"
case 801...804:
return "cloud.bolt"
default:
return "cloud"
}
}
}
Reference
この問題について(第13部:CoreLocationと完全な注釈付きコード(復習)を使用する), 我々は、より多くの情報をここで見つけました
https://velog.io/@msi753/Udemy-iOS-섹션13-코드-주석
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
// WeatherViewController.swift
import UIKit
import CoreLocation
class WeatherViewController: UIViewController {
@IBOutlet weak var conditionImageView: UIImageView!
@IBOutlet weak var temperatureLabel: UILabel!
@IBOutlet weak var cityLabel: UILabel!
@IBOutlet weak var searchTextField: UITextField!
@IBOutlet weak var currentLocation: UIButton!
var weatherManager = WeatherManager()
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
// 위치 요청 전에 미리 위임해야 한다
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.requestLocation() //one-time 한 번만
//locationManager.startUpdatingLocation() //내비게이션처럼 이동하는 정보를 계속 수집
// WeatherViewController가 weatherManager를 위임한다
weatherManager.delegate = self
searchTextField.delegate = self
}
@IBAction func locationPressed(_ sender: UIButton) {
locationManager.requestLocation()
}
}
//MARK: - UITextFieldDelegate, WeatherManagerDelegate
extension WeatherViewController: UITextFieldDelegate {
@IBAction func searchPressed(_ sender: UIButton) {
//키보드 해제
searchTextField.endEditing(true)
print(searchTextField.text!)
}
// should가 들어가면 bool을 return받아서 행동을 정한다
// return(Go)를 눌렀을 때
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
searchTextField.endEditing(true)
print(searchTextField.text!)
return true
}
// 유효성 검사
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
// 아무것도 없으면 멈추고, 아니면 Type something 보여주기
if textField.text != "" {
return true
} else {
textField.placeholder = "Type something"
return false
}
}
// 텍스트 필드에 글자 입력 후 return이나 버튼을 눌러 입력한 후
// 키보드를 해제했을 때 텍스트 필드 공백으로 만들기
func textFieldDidEndEditing(_ textField: UITextField) {
if let city = searchTextField.text {
weatherManager.fetchWeather(cityName: city)
}
searchTextField.text = ""
}
}
//MARK: - WeatherManagerDelegate
extension WeatherViewController: WeatherManagerDelegate {
// delegate method의 parameter규칙
// argument(밖에서 호출), parameter(안에서 사용, external과 internal이 있음)
// delegate method를 생성시킨 data type WeatherManager를 앞에 써주고 external parameter는 생략표시(_) 한다
func didUpdateWeather(_ weatherManager: WeatherManager, weather: WeatherModel) {
// 클로저 안에서는 self를 써준다
DispatchQueue.main.async {
self.temperatureLabel.text = weather.temperatureString
self.conditionImageView.image = UIImage(systemName: weather.conditionName)
self.cityLabel.text = weather.cityName
}
}
func didFailWithError(error: Error) {
print(error)
}
}
//MARK: - CLLocationManagerDelegate
extension WeatherViewController: CLLocationManagerDelegate {
//CL core Location
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.last {
locationManager.stopUpdatingLocation()
let lat = location.coordinate.latitude
let lon = location.coordinate.longitude
weatherManager.fetchWeather(latitude: lat, longitude: lon)
}
}
// 조건에 따라 에러 메서드(아래)도 반드시 구현해야 한다
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(error)
}
}
//
// WeatherManager.swift
// Clima
//
// Created by Etoday on 2021/02/15.
// Copyright © 2021 App Brewery. All rights reserved.
//
import Foundation
import CoreLocation
protocol WeatherManagerDelegate {
func didUpdateWeather(_ weatherManager: WeatherManager, weather: WeatherModel)
func didFailWithError(error: Error)
}
struct WeatherManager {
let weatherURL = "https://api.openweathermap.org/data/2.5/weather?appid=42250e4b3738d98ef5dae4a4635b68fd&units=metric"
var delegate: WeatherManagerDelegate?
func fetchWeather(cityName: String) {
let urlString = "\(weatherURL)&q=\(cityName)"
performRequest(with: urlString)
}
func fetchWeather(latitude: CLLocationDegrees, longitude: CLLocationDegrees) {
let urlString = "\(weatherURL)&lat=\(latitude)&lon=\(longitude)"
performRequest(with: urlString)
}
func performRequest(with urlString: String) {
//1. Create a URL
if let url = URL(string: urlString) {
// 2. Create a URLSession 기본 설정(브라우저)
let session = URLSession(configuration: .default)
// 3. Give the session a task
let task = session.dataTask(with: url) { (data, response, error) in
// 에러 처리
if error != nil {
self.delegate?.didFailWithError(error: error!)
return // exit
}
// parse into JSON format 파싱해서 delegate를 활용해서 WeatherViewController에 띄우기
if let safeData = data {
// 클로저 안에서 메서드를 호출할 때는 self를 써줘야 한다
// 파싱이 성공했을 때 delegate가 있으면 didUpdateWeather를 실행시킨다
if let weather = self.parseJSON(safeData) {
self.delegate?.didUpdateWeather(self, weather: weather)
}
}
}
// 4. Start the task
task.resume()
}
}
func parseJSON(_ weatherData: Data) -> WeatherModel? {
let decoder = JSONDecoder()
// input으로 object가 아니라 type을 받는데, .self를 붙여 type object의 참조값을 사용한다
// WeatherData structure을 사용해 decode를 시도한다
do {
let decodedData = try decoder.decode(WeatherData.self, from: weatherData)
let id = decodedData.weather[0].id
let temp = decodedData.main.temp
let name = decodedData.name
let weather = WeatherModel(conditionId: id, cityName: name, temperature: temp)
return weather
} catch {
delegate?.didFailWithError(error: error)
return nil
}
}
}
//
// WeatherData.swift
// Clima
// 여기는 JSON Parsing하기 위한 곳
// Created by Etoday on 2021/02/15.
// Copyright © 2021 App Brewery. All rights reserved.
//
import Foundation
//Decodable+Encodable -> Codable
struct WeatherData: Codable {
let name: String
// JSON의 일부분 (예시)
// main안에는 object{}가 들어있음
// "main": {
// "temp": 23.48,
// "pressure": 1024,
// "humidity": 40,
// "temp_min": 21,
// "temp_max": 25
// }
let main: Main
// weather안에는 [] 배열이 들어있음
// "weather": [
// {
// "id": 803,
// "main": "Clouds",
// "description": "broken clouds",
// "icon": "04n"
// }
// ]
let weather: [Weather]
}
// 변수명이 JSON의 변수명과 정확히 일치해야 한다
struct Main: Codable {
let temp: Double
}
struct Weather: Codable {
let description: String
let id: Int
}
//
// WeatherModel.swift
// Clima
// 여기는 화면에 보여줄 데이터를 계산하기 위한 곳
// Created by Etoday on 2021/02/15.
// Copyright © 2021 App Brewery. All rights reserved.
//
import Foundation
struct WeatherModel {
//stored property
public let conditionId: Int
public let cityName: String
public let temperature: Double
public var temperatureString: String {
return String(format: "%.1f", temperature)
}
//computed property (var 사용)
var conditionName: String {
switch conditionId {
case 200...232:
return "cloud.bolt"
case 300...321:
return "cloud.drizzle"
case 500...531:
return "cloud.rain"
case 600...622:
return "cloud.snow"
case 701...781:
return "cloud.fog"
case 800:
return "sun.max"
case 801...804:
return "cloud.bolt"
default:
return "cloud"
}
}
}
Reference
この問題について(第13部:CoreLocationと完全な注釈付きコード(復習)を使用する), 我々は、より多くの情報をここで見つけました https://velog.io/@msi753/Udemy-iOS-섹션13-코드-주석テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol