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

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

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

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

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

Swift

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

Q&A

解決済

1回答

970閲覧

[Swift]Fatal error: Unexpectedly found nil while unwrapping an Optional value

Jonny_dayo

総合スコア48

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

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

Swift

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

0グッド

0クリップ

投稿2019/10/01 02:16

編集2019/10/01 04:10

前提・実現したいこと

取得したJSONデータをTableviewに反映したいのですが、ビルド時に表題のエラーが出て落ちてしまいます。

発生している問題・エラーメッセージ

Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

該当のソースコード

Swift

1self.nameArray.append(name!) 2self.amountArray.append(amount!) 3self.taniArray.append(tani!) 4self.priceArray.append(price!)

全文ソースコード

GoogleDataSwift

1 2import Foundation 3class GoogleData { 4 5var name: String = "" 6var amount: String = "" 7var tani: String = "" 8var price: String = "" 9 10}

ViewController

1import Alamofire 2import UIKit 3import SwiftyJSON 4 5class ViewController: UIViewController, UINavigationControllerDelegate, UITableViewDelegate, UITableViewDataSource { 6 7 var googleData = GoogleData() 8 var nameArray = [String]() 9 var amountArray = [String]() 10 var taniArray = [String]() 11 var priceArray = [String]() 12 13@IBOutlet var tableView: UITableView! 14 15override func viewDidLoad() { 16 super.viewDidLoad() 17 18 tableView.delegate = self 19 tableView.dataSource = self 20 21 getData() 22 23 } 24 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 25 return nameArray.count 26 } 27 28 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 29 let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "Cell") 30 31 cell.textLabel?.text = self.nameArray[indexPath.row] 32 cell.detailTextLabel?.text = self.amountArray[indexPath.row] 33 cell.textLabel?.adjustsFontSizeToFitWidth = true 34 cell.detailTextLabel?.adjustsFontSizeToFitWidth = true 35 cell.textLabel?.numberOfLines = 1 36 cell.detailTextLabel?.numberOfLines = 1 37 cell.accessoryType = .checkmark 38 39 return cell 40 41 } 42 43func getData(){ 44 let text = "https://script.google.com/macros/s/AKfycbw1IzuulWfaxTtgsNS9Yi5iUNeBqBHy1XC-wV0IOBiAjpzsw98/exec" //取得したいURL 45 let url = text.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) 46 AF.request(url!, method: .get, parameters: nil, encoding: JSONEncoding.default).responseJSON { (response) in 47 48 print(response) 49 switch response.result{ 50 51 case .success: 52 53 JSON(response.data!).forEach { 54 print($0.1["name"].string as Any) 55 56 let json:JSON = JSON($0 as Any) 57 let name = json["name"].string 58 let amount = json["amount"].string 59 let tani = json["tani"].string 60 let price = json["price"].string 61 62 self.nameArray.append(name!) 63 self.amountArray.append(amount!) 64 self.taniArray.append(tani!) 65 self.priceArray.append(price!) 66 } 67 68 case .failure(let error): 69 print(error) 70 } 71 72 self.tableView.reloadData() 73 } 74 } 75 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 76 print("select - (indexPath)") 77 } 78 79 func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) { 80 print("deselect - (indexPath)") 81 } 82}

試したこと

Codableを利用してみたり、強制アンラップをかけてみたのですが、エラー消えませんでした…

ツールのバージョン

Xcode : Version 11.0
Swift : Apple Swift version 5.1

ビルド結果

イメージ説明
イメージ説明

追記2

イメージ説明

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hayabusabusash

2019/10/01 03:02 編集

強制アンラップしてappendしている部分があると思いますが、 appendする前にjsonを表示してみるのはどうですか? →すみませんされているようですね。 そのprintされている結果をみることはできますか?
Jonny_dayo

2019/10/01 03:31

@hayabusabusash さん またまたありがとうございます泣 ビルドした時に右下に出てくるやつのスクショを貼らせていただきました! ご確認何卒よろしくお願い致します…
hayabusabusash

2019/10/01 03:40

確認しました!ありがとうございます????‍♂️ とりあえずエラーなしで取れたので、続きは回答に書きます。
guest

回答1

0

ベストアンサー

JSONから値を取り出す時に失敗しているようです。

とりあえずJSONのパースはDecodableを使った方が楽かつ安全なので、
GoogleDataを以下のように修正しました。

Swift

1struct GoogleData: Decodable { 2 let name: String 3 let amount: Double 4 let tani: String 5 let price: Int 6 7 private enum CodingKeys: String, CodingKey { 8 case name 9 case amount 10 case tani 11 case price 12 } 13}

現在JSONを辞書配列にしてforEachで回していますが、
Decodableにすることで以下のように書くことができます。

Swift

1switch response.result{ 2 case .success: 3 do { 4 let datas = try JSONDecoder().decode([GoogleData].self, from: response.data!) 5 print(datas) 6 7 // appendのあたりは省略します 8 } catch let error { 9 // JSON -> GoogleData にデコード失敗 10 print(error) 11 } 12 case .failure(let error): 13 // 省略します

こうすることでJSONからデコードした際になぜ失敗したのか(キーの名前が違うなど)がわかりやすくなります。

一度これで確認してみてはもらえませんか?

コードの追記(2019/10/01)

JSONから値を取り出しているforEachの部分はいりませんね。
なので以下のようになります。

Swift

1func getData(){ 2 let text = "https://script.google.com/macros/s/AKfycbw1IzuulWfaxTtgsNS9Yi5iUNeBqBHy1XC-wV0IOBiAjpzsw98/exec" //取得したいURL 3 let url = text.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) 4 AF.request(url!, method: .get, parameters: nil, encoding: JSONEncoding.default).responseJSON { (response) in 5 switch response.result{ 6 case .success: 7 // 通信成功時 8 guard let data = response.data else { 9 return 10 } 11 12 do { 13 // googleDataはGoogleDataの配列( [GoogleData] )になります。 14 let googleData = try JSONDecoder().decode([GoogleData].self, from: response.data!) 15 16 // 前のforEachとやっていることは同じです。 17 googleData.forEach { item in 18 self.nameArray.append(item.name) 19 self.amountArray.append("(item.amount)") 20 self.taniArray.append(item.tani) 21 self.priceArray.append("(item.price)") 22 } 23 } catch let error { 24 // JSON -> GoogleData にデコード失敗 25 print(error) 26 } 27 case .failure(let error): 28 // 通信の失敗 29 print(error) 30 } 31 self.tableView.reloadData() 32 } 33 }

未検証なので変数名とか間違えててエラーになるかもしれません...

投稿2019/10/01 03:54

編集2019/10/01 04:28
hayabusabusash

総合スコア767

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Jonny_dayo

2019/10/01 04:13

GoogleDataを修正したので、ViewControllerに記載していたGoogleData()を取りました。 回答頂いた内容を入れてみたのですが、エラーだらけで…絶対違いますよねこれ…理解不足ですみません…
hayabusabusash

2019/10/01 04:15

JSONデコードは一箇所でいいので、forEachの部分はいらないですね。 ちょっとコード載せますね。
Jonny_dayo

2019/10/01 04:35

うわああああああああできたああああああああ!!! ありがとうございます!ありがとうございます! 基礎的な質問ばかりしてしまいましたが、とても丁寧に細かく教えて頂いて… 本当に感謝の気持ちしかないですありがとうございました!!!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問