前提・実現したいこと
ライブドアのお天気APIからデータを取得しTableViewに表示する。
http://weather.livedoor.com/weather_hacks/webservice
発生している問題・エラーメッセージ
エラーメッセージはないものの、
TableViewに表示されず困っています。
そもそもなのですが、
API取得するURLってアクセスした際は、
真っ白なページにJSONだけ記載されたページに遷移していたような気がするのですが、
これってもしかして、サービスが終了、またはURLが変わったということでしょうか?
東京の天気
http://weather.livedoor.com/forecast/webservice/json/v1?city=130010
他の地域参考
livedoor Weather Hacks APIで、お天気データのJSONを取得するための1次細分区(cityタグ)の地域id一覧まとめ
該当のソースコード
WeatherApiModel
1import Foundation 2import Alamofire 3import RealmSwift 4 5class WeatherApiModel : Object { 6 7 //Realmから受け取るデータ 8 var weatherLists: [DbTable]? 9 10 weak var delegate: ViewDelegate? 11 12 func weatherApi(){ 13 //お天気APIから東京の天気を取得する(130010=東京) 14// let url:String = "http://weather.livedoor.com/forecast/webservice/json/v1?city=130010" 15 let url:URL = URL(string: "http://weather.livedoor.com/forecast/webservice/json/v1?city=130010")! 16 let task = URLSession.shared.dataTask(with: url){ data, response, error in 17 if let error = error{ 18 print(error.localizedDescription) 19 return 20 } 21 if let response = response as? HTTPURLResponse { 22 print("response.statusCode = (response.statusCode)") 23 } 24 } 25 task.resume() 26 27 AF.request(url, method: .get, encoding: JSONEncoding.default).responseString { response in 28 29 switch response.result { 30 case .success: 31 guard let data = response.data else {return} 32 guard let weatherNews = try? JSONDecoder().decode(WeatherNews.self, from: data) else {return} 33 print("success") 34 35 let forecasts = weatherNews.forecasts 36 37 guard let realm = try? Realm() else {return} 38 print(Realm.Configuration.defaultConfiguration.fileURL!) 39 40 let weather = [DbTable(value: ["date": forecasts[0].date,"telop": forecasts[0].telop,"iconUrl": forecasts[0].image.url]), 41 DbTable(value: ["date": forecasts[1].date,"telop": forecasts[1].telop,"iconUrl": forecasts[1].image.url]), 42 DbTable(value: ["date": forecasts[2].date,"telop": forecasts[2].telop,"iconUrl": forecasts[2].image.url])] 43 44 try? realm.write { 45 realm.add(weather, update: .modified) 46 } 47 48 self.weatherLists = Array(realm.objects(DbTable.self)) 49 50 guard let weatherResult = self.weatherLists else {return} 51 self.delegate?.updateAPI(weatherLists: weatherResult) 52 53 case .failure(let error): 54 print(error) 55 } 56 } 57 } 58}
基本的に上記のコードを見ていただけば大丈夫だと思いますが、
念の為、全てのコードを載せておきますので、参考までにどうぞ。
ViewController
1import UIKit 2import Alamofire 3import Foundation 4import RealmSwift 5 6protocol ViewDelegate: class { 7 func updateAPI(weatherLists : [DbTable]) 8} 9 10class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, ViewDelegate { 11 12 var weatherApiModel = WeatherApiModel() 13 var weatherListsResult: [DbTable]? 14 @IBOutlet weak var table:UITableView! 15 16 override func viewDidLoad() { 17 super.viewDidLoad() 18 19 receiveEvent() 20 21 } 22 23 func receiveEvent() { 24 weatherApiModel.delegate = self 25 weatherApiModel.weatherApi() 26 } 27 28 func updateAPI(weatherLists : [DbTable]) { 29 weatherListsResult = weatherLists 30 self.table.reloadData() 31 } 32 33 //Table Viewセル数指定 34 func tableView(_ table: UITableView, 35 numberOfRowsInSection section: Int) -> Int { 36 guard let weatherListCount = weatherListsResult?.count else { return 0 } 37 return weatherListCount 38 } 39 40 //各セル要素設定 41 func tableView(_ table: UITableView, 42 cellForRowAt indexPath: IndexPath) -> UITableViewCell { 43 44 guard let cell = table.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as? TableViewCell else {fatalError("cell error")} 45 guard let date = weatherListsResult?[indexPath.row].date, 46 let telop = weatherListsResult?[indexPath.row].telop else {fatalError("error")} 47 48 cell.dateLabel.text = date 49 cell.telopLabel.text = telop 50 51 guard let iconUrl = weatherListsResult?[indexPath.row].iconUrl else {fatalError("error")} 52 guard let url = URL(string: iconUrl) else {fatalError("error")} 53 if let iconData = try?Data(contentsOf: url) { 54 cell.iconImageView?.image = UIImage(data: iconData) 55 } 56 57 return cell 58 } 59}
DbTable
1import Foundation 2import RealmSwift 3 4class DbTable: Object, Codable { 5 // カラム定義 6 @objc dynamic var id: String = NSUUID().uuidString 7 @objc dynamic var date: String = "" 8 @objc dynamic var telop: String = "" 9 @objc dynamic var iconUrl: String = "" 10 11 override static func primaryKey() -> String? { 12 return "id" 13 } 14 15} 16
CodableModel
1import Foundation 2 3struct WeatherNews: Codable { 4 let title: String 5 let publicTime: String 6 let forecasts: [Forecast] 7 let location: WeatherLocation 8 let description: WeatherDescription 9} 10 11struct Forecast: Codable { 12 let dateLabel: String 13 let telop: String 14 let date: String 15 let temperature: TemperatureCollection 16 let image: WeatherImage 17} 18 19struct TemperatureCollection: Codable { 20 let min: Temperature? 21 let max: Temperature? 22} 23 24struct Temperature: Codable{ 25 let celsius: String 26 let fahrenheit: String 27} 28 29struct WeatherImage: Codable { 30 let width: Int 31 let height: Int 32 let title: String 33 let url: String 34} 35 36struct WeatherLocation: Codable { 37 let city: String 38 let area: String 39 let prefecture: String 40} 41 42struct WeatherDescription: Codable { 43 let text: String 44 let publicTime: String 45}
MainStoryBoard
※各パーツが接続しているかは確認済みです。
試したこと
もしや正常にレスポンスが返ってきてないのかと思い下記のサイトを参考に
レスポンスコードを調べたところ「200」で正常でした。
Swift URLSessionでHTTPレスポンスコードを取得する方法
補足情報(FW/ツールのバージョンなど)
・version
MacOS:Catalina 10.15.5
Xcode:11.6
iOS:13.6
回答1件
あなたの回答
tips
プレビュー