9. Weather Location App

18110 ワード


今回の講座では位置ベースの天気アプリを作成しました.

プロジェクトから学んだこと


UItextField、プロトコルと委任、拡張、URLセッションとのネットワークとJSONデータ構文を分析します.

UITextField


TextFieldでは、ユーザーが入力したデータを使用できます.そうなるとキーボードが出てきますが、キーボードを閉じたり、キーボードを開いたりできるコードを覚えました.
@IBAction func searchPressed(_ sender: UIButton) {
        // 검색 버튼을 누르면 endEditing 되게끔
        // 그러면 키보드가 내려감
        searchTextField.endEditing(true)
        print(searchTextField.text!)
        
    }
searchTextField.endEditing(true)終了時にキーボードが閉じるコードを入力します.

ReturnButtonTapped

// TextField에서 Return 버튼을 눌렀을 경우(여기선 Go버튼)
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        print(searchTextField.text!)
        searchTextField.endEditing(true)
        return true
    }
キーボードのリターンキーを押しても、キーボードは一緒に閉じます.

textFieldShouldEditing VS textFieldDidEditing


この違いはすでに異なる文字で紹介されている.
textFieldEditingとtextFieldShouldEditingの違い
この文章を参考にしてもいいですが、簡単に言えば
役が少し違う.ShouldEditingはDelegateに尋ねるキャラクターです.
ねえ、入力が終わりました.何をしますか.
一方、DidEditingは一方的な通報だ.
「いやあ、入力が終わったら、そのまま閉じちゃった」
こんな感じで
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
        if textField.text != "" {
            return true
        } else {
            textField.placeholder = "Type something"
            return false
        }
    }
    
func textFieldDidEndEditing(_ textField: UITextField) {
        // 아래에 지워지기 전에 도시 이름을 사용하고 싶음
        // searchTextField.text 가 옵셔널 스트링이니까, 
        // 사용하려면 언래핑 해야 한다.
        // 따라서 if let 구문을 사용했다.
        if let city = searchTextField.text {
            weatherManager.fetchWeather(cityName: city)
            
        }
        
        // 입력이 끝났을 때 현재 입력했던것은 자연스레 지움
        searchTextField.text = ""
    }
この2つのコードの使用場所は少し違います.

protocol And delegate


protocol
// Delegate Design Pattern 구현
protocol WeatherManagerDelegate {
    func didUpdateWeather(_ weatherManager: WeatherManger, weather: WeatherModel)
    // weatherManager에서 오류를 전달할때 도와주는 delegate(메서드)
    func didFailWithError(error: Error)
}
プロトコルは規約、制約です.
ああ、だからこれを持っていなければなりません.程度で説明できる.
上のコードは、天気表示部分に必要なものを定義しています.
コードは、天気を更新するためにdidUpdateWeatherが使用されていることを示しています.
エラーを返すdidFailWithErrorがあります.
これらの必須要素は、プロトコルとして定義して使用できます.
delegate
代理の役割を果たす.つまり,コードに直接アクセスするためではなく,コード間のコミュニケーションを円滑にするためである.
override func viewDidLoad() {
        super.viewDidLoad()
        
        // delegate 를 위치 업데이트 이전에 해줘야 에러가 발생하지 않는다.
        locationManager.delegate = self
        // 사용자에게 위치 권한을 요청하는 팝업이 화면에 표시된다.
        locationManager.requestWhenInUseAuthorization()
        // 위치를 한번만 업데이트 한다.
        locationManager.requestLocation()
        
        // weatherManager 의 delegate를 ViewController로 설정해줘야,
        // delegate의 주소가 제대로 입력이 된다.
        // *중요*
        
        weatherManager.delegate = self
        
        // TextField에서 일어나는 것들에 대해 위 클래스 자신에게 상황을 알려주는 것이다.
        // TextField에서 알림을 받는 컨트롤러는 뷰 컨트롤러를 대리자로 설정하는 것이다.
        // self는 ViewController를 가리킨다
        searchTextField.delegate = self
    }
selfが他の場所で起こったことを伝えることができます
これで管理しやすい(?)Delegateもう一度聞いてみよう

extension


Extensionは既存のものに機能を追加したり、依頼を基準に配布したりすることができます.
extension WeatherViewController: WeatherManagerDelegate {
    // WeatherManagerDelegate 에 필수적으로 들어가 있는
    // didUpdateWeather가 정의되어있는 상태이니 에러가 발생하지 않는다.
    // 그리고 이 메서드가 데이터를 가져오는 곳은 weatherManager 이니 ID에 weatherManager 를 추가해줘야한다.
    func didUpdateWeather(_ weatherManager: WeatherManger, weather: WeatherModel) {
        // 클로저는 백그라운드에서 사용자 인터페이스를 업데이트하기 위해 메인 스레드를 호출해야 합니다.
        DispatchQueue.main.async {
            self.temperatureLabel.text = weather.temperatureString
            self.conditionImageView.image = UIImage(systemName: weather.conditionName)
            self.locationLabel.text = weather.cityName
        }
        
    }
    // Delegate에서 선언한 메서드 정의
    func didFailWithError(error: Error) {
        print(error)
    }
}
一般的には、WeatherViewController 内にあるviewDidLoad()の方法で用いられるDelegateの方法に分けられる.
以上のコードは、天気情報の更新方法を含むDelegateである.これもextensionにまとめることができる.

URLセッションとのネットワークとJSONデータ構文を解析します。


これも別の文章にまとめられています.文章はかなり長いので、リンクで代用します.
iOS API JSONデータのインポート(気象API)
iOS API JSON Parsing(気象API)の実行

Location Update

import CoreLocation

class WeatherViewController: UIViewController {
    let locationManager = CLLocationManager()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // delegate 를 위치 업데이트 이전에 해줘야 에러가 발생하지 않는다.
        locationManager.delegate = self
        // 사용자에게 위치 권한을 요청하는 팝업이 화면에 표시된다.
        locationManager.requestWhenInUseAuthorization()
        // 위치를 한번만 업데이트 한다.
        locationManager.requestLocation()
        
     }
 }
 
 extension WeatherViewController: CLLocationManagerDelegate {
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        // last 는 배열의 마지막 원소, 그리고 last는 옵셔널이기에 if let 구문 사용
        if let location = locations.last {
            // 위치를 받아오는(찾아낸)즉시 찾는걸 중지시킨다.
            locationManager.stopUpdatingLocation()
            let lat = location.coordinate.latitude
            let lon = location.coordinate.longitude
            // 그리고 나서 패치에 해당 좌표를 옮겨준다.
            weatherManager.fetchWeather(latitude: lat, longitude: lon)
        }
        
    }
座標または位置情報を取得するには、上記のCoreLocationをインポートする必要があります.
その後、viewDidLoad()の上記コードを使用して情報を取得し、拡張機能として追加することができます.

プロジェクトを行うときの感想と勉強


APIを正しく使うのは難しすぎて、今も難しくて、慣れていません.でも、何度も使うより慣れると信じています.そして、extensionやdelegateなどいろいろなものを理論しか知らないレベルにアップグレードします.しかし、まだ熟練していないので、多くの場所で使うべきです.
ロケも始まりました.実は、授業前に触った記録がありますが、この部分はそんなに難しくありません.
だんだん、勉強の感じがいいです.もっと頑張ろう