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

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

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

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

Q&A

解決済

1回答

929閲覧

APIで受信したデーターを変数への代入方法について教えて下さい。

bkyj5374

総合スコア18

Swift

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

0グッド

0クリップ

投稿2019/06/28 04:26

編集2019/06/28 04:29

APIで受け取った情報をTableviewのCellに貼り付けたいです。
以前はTestData1の形に変換して、Cellに渡そうと思っていたのですが、パースしたjsonをそのまま利用する方が好ましいとのアドバスを受け、
以下のように記述してみました。
実行するとエラーはでませんが、テーブルには何も表示されません。

swift

1import UIKit 2 3 4class TableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { 5 6 7 @IBOutlet weak var APPNAME: UILabel! 8 @IBOutlet weak var Change: UIButton! 9 @IBOutlet var ApprovalTableView: UITableView! 10 11 // 12 var TestData1 : [[String:String]] = [ 13 ["ID":"19540921","NAME":"安倍 晋三","DOCUCODE":"https://www.abcdefg.com/19540921"], 14 ["ID":"19400920","NAME":"麻生 太郎","DOCUCODE":"https://www.abcdefg.com/19400920"], 15 ["ID":"19630110","NAME":"河野 太郎","DOCUCODE":"https://www.abcdefg.com/19630110"] 16 ] 17 18 //送られてくるJSONに相当する構造体を準備する 19 struct JsonForm : Codable { 20 var ID : String 21 var NAME : String 22 var DOCUCODE : String 23 24 } 25 26 //ここが不安 27 var CellValue = [JsonForm]() 28 29 //ここからviewDidLoad 30 override func viewDidLoad() { 31 super.viewDidLoad() 32 33 // 34 ApprovalTableView.dataSource = self 35 ApprovalTableView.delegate = self 36 37 38 //APIへGET送信 39 let listUrl = "https://省略" 40 let APIurl = URL(string: listUrl)! 41 42 // 43 URLSession.shared.dataTask(with: APIurl) { (data, response, error) in 44 45 // 46 if (error == nil) { 47 // API通信成功 48 49 // 50 guard let data = data else { return } 51 52 // 53 do { 54 //パース:jsonはArray<JsonForm> 55 let json:[JsonForm] = try JSONDecoder().decode([JsonForm].self, from: data) 56 57 //変数に代入 58 self.CellValue = json 59 60 } catch { 61 62 print(error) 63 64 } 65 66 } else { 67 // API通信失敗 68 print("API NG") 69 70 } 71 72 }.resume() 73 74 } 75 76 //画面遷移させる時に値を渡す 77 override func prepare(for segue: UIStoryboardSegue, sender: Any? ) { 78 79 // 80 if let detailVC = segue.destination as? DetailViewController, let indexPath = sender as? IndexPath { 81 detailVC.message = CellValue[indexPath.row].DOCUCODE 82 83 } 84 85 } 86 87 //セクションの数 88 func numberOfSections(in tableView: UITableView) -> Int { 89 return 1 90 } 91 92 //セルの数 93 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 94 //return TestData1.count 95    return CellValue.count 96 } 97 98 //セルに描写 99 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 100 let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath ) 101 102 //tag1 103 let Label1 = cell.viewWithTag(1) as? UILabel 104 //Label1?.text = TestData1[indexPath.row]["ID"] 105 Label1?.text = CellValue[indexPath.row].ID 106 107 //tag2 108 let Label2 = cell.viewWithTag(2) as? UILabel 109 //Label2?.text = TestData1[indexPath.row]["NAME"] 110 Label2?.text = CellValue[indexPath.row].NAME 111 112 //tag3 113 let Label3 = cell.viewWithTag(3) as? UILabel 114 //Label3?.text = TestData1[indexPath.row]["DOCUCODE"] 115 Label3?.text = CellValue[indexPath.row].DOCUCODE 116 117 // 118 return cell 119 120 } 121 122 //セルの高さを決める 123 func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 124 return 100 125 } 126 127 //セルをタップした時 128 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 129 performSegue(withIdentifier: "MainToDetail", sender: indexPath) 130 131 } 132 133} 134

jsonを代入する変数の宣言の問題なのか、代入後の変数がスコープ範囲外なのか、代入後の変数の扱いが間違っているのかがわかりません。
基本的な何かが欠けていると思うのですが、ご教授お願い致します。

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

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

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

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

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

hayabusabusash

2019/06/28 04:38 編集

//変数に代入 self.CellValue = json この下で self.ApprovalTableView.reloadData() では表示されませんか?
bkyj5374

2019/06/28 05:01

返信ありがとうございます。 真下に追記してみたところ、 self.CellValue = json self.ApprovalTableView.reloadData() 実行すると紫色で UITableView.reloadData() must be used from main thread only となります。 そこで「メインスレッドからのみ使用」との意味のようなので、外しているかもしれませんが、resume()の次の行で実行してみましたが、エラーも出ず表示もされない状況です。
hayabusabusash

2019/06/28 05:08

確認ありがとうございます! 非同期処理だとがすっかり抜けていました。申し訳ありません。 少し確認したいのですが、 同じ変数に代入の下に以下のような記述はできますでしょうか? DispatchQueue.main.async { self.ApprovalTableView.reloadData() }
bkyj5374

2019/06/28 05:25

表示されました!!! セルをタップした行の動作も問題なさそうです。 今、感動しています。 ありがとうございます。 追加のお願いで恐縮ですが、理解を深めておきたいのです。 この DispatchQueue.main.async { self.ApprovalTableView.reloadData() } を変数代入の直後に記述する事で内部的にどのような処理を行っているのかを解説頂けると助かります。
hayabusabusash

2019/06/28 05:31

よかったです! 長くなりそうなので回答の方に記述させていただきます。
guest

回答1

0

ベストアンサー

URLSessionでのAPIとの通信ですが、
こちら非同期の処理になりますので、メインスレッドではないスレッドで実行されます。(参考)
また、UIの描画はメインスレッドでしか実行できないため先程のエラーが出力されます。

UITableView.reloadData() must be used from main thread only

なのでTableViewの更新のようなUIの再描画はメインスレッドで行うように指定します。
それが以下の部分です。Swiftのスレッド関連に関してはこちらを参考にしてください。

Swift

1DispatchQueue.main.async { 2 self.ApprovalTableView.reloadData() 3}

あとTableViewに表示するデータ(今回の場合CellValueですね)を更新したい場合はリロードするようにしてください。
そうしないといくらメインスレッドでデータを更新してもTableViewに反映されません。

Swift

1 tableView.reloadData()

投稿2019/06/28 05:41

hayabusabusash

総合スコア767

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

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

bkyj5374

2019/06/28 05:48

丁寧に対応頂きとても感謝しております。 いただいた解説は今の私では理解に至りませんが、繰り返し読んで理解できるよう努めます。 ありがとうございました。
hayabusabusash

2019/06/28 08:13

私もまだまだ未熟なため、わかりやすい解説にならず申し訳ないです。 非同期の処理は色々考えることが多く大変ですが、 使いこなせるようになると開発の幅が大きく広がると思います。 URLSessionの他にも通信ができるライブラリ等を使ってみるとより理解が深まると思うので ぜひ試してみてはいかがでしょうか? この回答で今回の問題が解決できたなら質問を解決済みにしておいてはいただけないでしょうか? もし他に不明点があるなら別の質問としてあげていただければお答えいたします!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問