質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

解決済

[Swift] delegateがnilになってしまう

AdamYoneda
Adam_Yoneda

総合スコア10

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

1回答

0評価

0クリップ

156閲覧

投稿2022/06/18 05:39

編集2022/06/18 19:05

実現したいこと

swift初学者です。delegateについて自力で解決できないところがあり、ご回答いただけますとありがたいです。

位置情報を元に天気に関する情報をAPIから取得し、その内容を表示するアプリを作成しています。
APIから取得したデータをdelegateを用いて、WeatherManagerクラスからWeatherViewControllerクラスにWeatherModelオブジェクトを渡して処理を実行しようとしています。

現在の問題

WeatherManagerのdelegateがnilになったままで、処理が実行されません。

環境

Xcode(ver 13.3.1)
macOS Monterey(ver12.3.1)

該当のコード

swift

import Foundation // delegate design parttern protocol WeatherManagerDelegate:AnyObject { func didUpdateWeather(inputWeatherModel: WeatherModel) } class WeatherManager { // delegate weak var delegate: WeatherManagerDelegate? // fetchCoordinate func fetchWeather(urlString: String) { performRequest(inputURLString: urlString) } // performRequest func performRequest(inputURLString: String) { // 1. Create URL if let url = URL(string: inputURLString) { // 2. Create URLSession let session = URLSession(configuration: .default) // 3. Give the URLSession a task let task = session.dataTask(with: url) { (data, response, error) in if error != nil { print(error!) return } if let safeData = data { if let weather = self.parseJSON(JSONobject: safeData) { // ---------- 問題の箇所 ---------- self.delegate?.didUpdateWeather(inputWeatherModel: weather) } } } // 4. Start the task task.resume() } } // parse JSON object func parseJSON(JSONobject: Data) -> WeatherModel? { let decoder = JSONDecoder() do { let decodedData = try decoder.decode(WeatherData.self, from: JSONobject) 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 { print(error) return nil } } }

swift

import UIKit class WeatherViewController: UIViewController, UITextFieldDelegate, WeatherManagerDelegate { @IBOutlet weak var conditionImageView: UIImageView! @IBOutlet weak var temperatureLabel: UILabel! @IBOutlet weak var searchTextField: UITextField! @IBOutlet weak var cityLabel: UILabel! var weatherManager = WeatherManager() var coordinateManager = CoordinateManager() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. searchTextField.delegate = self searchTextField.keyboardType = .asciiCapable weatherManager.delegate = self } @IBAction func searchPressed(_ sender: UIButton) { searchTextField.endEditing(true) } func textFieldShouldReturn(_ textField: UITextField) -> Bool { searchTextField.endEditing(true) return true } func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { if textField.text != "" { return true } else { textField.placeholder = "Type Something" return false } } func textFieldDidEndEditing(_ textField: UITextField) { if let city = searchTextField.text { coordinateManager.fetchCoordinate(cityName: city) } searchTextField.text = "" } // ---------- プロトコルのメソッド ---------- func didUpdateWeather(inputWeatherModel: WeatherModel) { print(inputWeatherModel.temperature) } }

swift

import Foundation struct WeatherModel { let conditionId: Int let cityName: String let temperature: Double }

swift

import Foundation struct CoordinateManager { // WeatherManager let weathetManager = WeatherManager() // geographical coordinates(lat, lon) 地理座標 let coordinateURL = "https://api.openweathermap.org/geo/1.0/direct?limit=1&appid=c8e60c6317c653a1789294c00f54ae19" // fetchCoordinate func fetchCoordinate(cityName: String) { let urlString = "\(coordinateURL)&q=\(cityName)" performRequest(inputURLString: urlString) } // transformURLString func transformURLString(_ string: String) -> URLComponents? { guard let urlPath = string.components(separatedBy: "?").first else { return nil } var components = URLComponents(string: urlPath) if let queryString = string.components(separatedBy: "?").last { components?.queryItems = [] let queryItems = queryString.components(separatedBy: "&") for queryItem in queryItems { guard let itemName = queryItem.components(separatedBy: "=").first, let itemValue = queryItem.components(separatedBy: "=").last else { continue } components?.queryItems?.append(URLQueryItem(name: itemName, value: itemValue)) } } return components! } // performRequest func performRequest(inputURLString: String) { // 1. Create URL let components = transformURLString(inputURLString) if let url = components?.url { // 2. Create URLSession let session = URLSession(configuration: .default) // 3. Give the URLSession a task let task = session.dataTask(with: url) {(data, response, error) in if error != nil { print(error!) return } if let safeData = data { self.parseJSON(JSONobject: safeData) } } // 4. Start the task task.resume() } } // parseJSON func parseJSON(JSONobject: Data) { let decoder = JSONDecoder() do { let decodedData = try decoder.decode([CoordinateData].self, from: JSONobject) let name = decodedData[0].name let lat = decodedData[0].lat let lon = decodedData[0].lon let coordinateModel = CoordinateModel(name: name, lat: lat, lon: lon) let weatherURL = coordinateModel.urlString // ------- WeatherManager fetchWeather --------- weathetManager.fetchWeather(urlString: weatherURL) } catch { print(error) } } }

swift

import Foundation struct CoordinateModel { let name: String let lat: Double let lon: Double // wheather 地理座標を元に検索した天気の情報 let weatherstr = "https://api.openweathermap.org/data/2.5/weather?" let str = "units=metric&appid=c8e60c6317c653a1789294c00f54ae19#" // computedproperty var urlString: String { return "\(weatherstr)&lat=\(lat)&lon=\(lon)&\(str)" } }

よろしくお願いいたします。

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

hoshi-takanori

2022/06/18 08:34

fetchWeather はどこで呼んでますか?
AdamYoneda

2022/06/18 08:41

失礼しました。 追加したコードのstruct CoordinateManager内の下の方で呼んでいます。 CoordinateManager内では先に都市名から地理座標を得るAPIを利用して、天気の情報を得るURLを作成しています。

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています