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

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

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

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

Swift

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

Q&A

解決済

2回答

701閲覧

【swift 】 定義の仕方

mita0

総合スコア40

Xcode

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

Swift

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

0グッド

0クリップ

投稿2019/08/22 05:58

編集2019/10/29 07:57

前提・実現したいこと

関数get()の中にあるforの中に定義しているvaluesをメンバ変数にしてで出力させたいです。

関数内での定義した定数(変数)の定義の仕方が理解が曖昧です。
そこも合わせて教えてほしいです。

初心者なので分からない細かく教えていただければ幸いです。
また足りない情報があれば追記するのでご指摘ください。

やりたいこととしては以下になります。
①searcbarのtextとgitのURLを合わせる(https://api.github.com/search/repositories?q=Google(Googleでtestしています))
②値を取り出して出力
③tableで表示(順に行なってるためtableは用意してません)

該当のソースコード

for value in array { let value = value as! Dictionary<String, Any>;() //Dictionaryに変換 //Dictionaryに変換後取り出す値の型を変換する let values = value["name"] as! String print(values) }

全体のソースコード

import UIKit class ViewController: UIViewController, UISearchBarDelegate, URLSessionDelegate { override func viewDidLoad() { super.viewDidLoad() searchBar.delegate = self searchBar.showsCancelButton = true // Do any additional setup after loading the view. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } @IBOutlet weak var searchBar: UISearchBar! @IBOutlet weak var tableView: UITableView! func searchBarSearchButtonClicked(_ searchBar:UISearchBar) { print("検索") print(searchBar.text!) get() } func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { print("キャンセル") } //アドレスデータを扱うURLクラス func get() { guard let url = URL(string: "https://api.github.com/search/repositories?q=(searchBar.text!)") else { print("no such file") return } //インスタンスの初期化 let session = URLSession.shared //ダウンロード処理が完了した時に戻されるタップル let task = session.dataTask(with: url, completionHandler: {(data, response, error) in DispatchQueue.main.async { let str = String(data: data!, encoding: String.Encoding.utf8) //print(str) do { //jsonをパースする(urlのjsonデータが全て入ってる) let json = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments) let jsons = json as! Dictionary<String, Any>;()           let array = jsons["items"] as! Array<Any>;() for value in array { let value = value as! Dictionary<String, Any>;() //Dictionaryに変換 //Dictionaryに変換後取り出す値の型を変換する let values = value["name"] as! String //print(values) print(values) } } catch{ print(error) } } }) //taskを動かす task.resume() } }

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

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

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

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

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

fuzzball

2019/08/22 06:10

>>func get()で出力させたいです。 get()のどこで出力させたいのでしょうか? また、get()の中ならメンバ変数にする必要はないと思いますが。
mita0

2019/08/22 06:17

修正しました。 追記情報足りていますか? 関数get()の中にあるforの中に定義しているvaluesをメンバ変数にしてで出力させたいです。
fuzzball

2019/08/22 06:20 編集

>>valuesをメンバ変数にしてで出力させたいです。 であれば、メンバ変数にして出力すればいいのではないでしょうか? なぜしないのでしょうか?
fuzzball

2019/08/22 06:40

そもそもarrayって何なんでしょうか?
mita0

2019/08/22 07:12

let array = jsons["items"] as! Array<Any>;()が抜けてました。 追記しています。
guest

回答2

0

動くかわかりませんが、ちょっといじりすぎたかもしれません。

swift

1import UIKit 2 3class ViewController: UIViewController, UISearchBarDelegate, URLSessionDelegate { 4 5 @IBOutlet weak var searchBar: UISearchBar! 6 7 @IBOutlet weak var tableView: UITableView! 8 9 // ★メンバ変数の定義 10 private var names = [String]() 11 12 override func viewDidLoad() { 13 super.viewDidLoad() 14 15 searchBar.delegate = self 16 searchBar.showsCancelButton = true 17 // Do any additional setup after loading the view. 18 } 19 20 override func didReceiveMemoryWarning() { 21 super.didReceiveMemoryWarning() 22 } 23 24 func searchBarSearchButtonClicked(_ searchBar:UISearchBar) { 25 print("検索") 26 print(searchBar.text!) 27 get() 28 } 29 30 func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { 31 print("キャンセル") 32 } 33 34 //アドレスデータを扱うURLクラス 35 func get() { 36 guard let url = URL(string: "https://api.github.com/search/repositories?q=(searchBar.text!)") else { 37 print("no such file") 38 return 39 } 40 41 //ダウンロード処理が完了した時に戻されるタップル 42 let task = URLSession.shared.dataTask(with: url) { (data, response, error) in 43 44 if let error = error { 45 print(error) 46 return 47 } 48 49 do { 50 //jsonをパースする(urlのjsonデータが全て入ってる) 51 let json = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments) 52 53 let jsons = json as! [String: Any] 54 55 var names = [String]() 56 for value in jsons.values { 57 let value = value as! [String: Any] //Dictionaryに変換 58 //Dictionaryに変換後取り出す値の型を変換する 59 let name = value["name"] as! String 60 names.append(name) 61 } 62 63 // ★メンバ変数の代入以降をメインスレッドで行うほうがメインスレッドにやさしい 64 DispatchQueue.main.sync { 65 self.names = names 66 67 // ★UIを更新するならここに書く 68 69 return 70 } 71 } catch { 72 print("error") 73 } 74 } 75 //taskを動かす 76 task.resume() 77 78 } 79 80} 81

あと、URLに渡す文字列はパーセントエンコードしないとだめそうですね。

投稿2019/08/22 06:31

takabosoft

総合スコア8356

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

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

mita0

2019/08/22 07:03

回答ありがとうございます。 パーセントエンコードしないとどうなるのでしょうか。 パーセントエンコードがよくわかってないです、、、
takabosoft

2019/08/22 07:07

URLにはルールがあり、パラメーターなどに例えば半角スペースを含める場合は半角スペースを%20に置き換えないといけない、といったルールが沢山あります。でないと正しく文字列をサーバーに渡せません。 昔qiitaに記事を書いた事があるので、そちらを参考にしてみてください。 https://qiita.com/takabosoft/items/50683d32e04f7d30a410
mita0

2019/08/22 07:09

ご丁寧にありがとうございます。 参考にさせていただきます。
mita0

2020/12/11 05:42 編集

確認よろしいでしょうか? ①forの上にnames = [String]()がなぜ二つあるのはなんででしょうか? ②[String]()とは? ③//★UIを更新するならここに書くにtableviewを更新する場合はどうかけばよろしいでしょうか?(searchBarで検索した際にtableviewでの表示が最終目標) 下記、現在のコードです。 import UIKit class ViewController: UIViewController, UISearchBarDelegate, URLSessionDelegate, UITableViewDelegate, UITableViewDataSource { //tableviewのcellの数 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.names.count } //cellの要素を func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "tableView", for: indexPath) cell.textLabel!.text = self.names[indexPath.row] return cell } override func viewDidLoad() { super.viewDidLoad() searchBar.delegate = self searchBar.showsCancelButton = true // Do any additional setup after loading the view. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } @IBOutlet weak var searchBar: UISearchBar! @IBOutlet weak var tableView: UITableView! var names: [String] = [] func searchBarSearchButtonClicked(_ searchBar:UISearchBar) { print("検索") print(searchBar.text!) get() } func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { print("キャンセル") } //アドレスデータを扱うURLクラス func get() { guard let url = URL(string: "https://api.github.com/search/repositories?q=(searchBar.text!)") else { print("no such file") return } //インスタンスの初期化 let session = URLSession.shared //ダウンロード処理が完了した時に戻されるタップル let task = session.dataTask(with: url, completionHandler: {(data, response, error) in DispatchQueue.main.async { print(self.names) let str = String(data: data!, encoding: String.Encoding.utf8) //print(str) do { //jsonをパースする(urlのjsonデータが全て入ってる) let json = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments) let jsons = json as! Dictionary<String, Any>;() ////arrayを定義する let array = jsons["items"] as! Array<Any>;() //arrayを表示する() //print(array[0]) //let dictionarys = dictionary["id"] //print(dictionarys as Any) var names: [String] = [] for value in array { let value = value as! Dictionary<String, Any>;() //Dictionaryに変換 //Dictionaryに変換後取り出す値の型を変換する //let values = value["name"] as! String self.names.append(value["name"] as! String) //print(values) // print(values) } print(self.names) } catch{ print(error) } } }) //taskを動かす task.resume() } }
takabosoft

2019/08/23 00:15

> ①forの上にnames = [String]()がなぜ二つあるのはなんででしょうか? 2つ?かどうかはわかりませんが、 ↓一つはメンバ変数 private var names = [String]() ↓もう一つはローカル変数ですね。 var names = [String]() 後半に記述していますが、なるべくメインスレッドを軽くしてあげることを優先するために、 別スレッドの処理の中でデータ(names)をすべて構築し、メインスレッドでは代入だけしておわるようにしてあります。 ↓この部分ですね。 DispatchQueue.main.sync { self.names = names } これがやりたいので、ローカルで一度names配列を作っています。 (私が独自でやっている手法なので一般的かどうかはわかりませんが) ②[String]()とは? var names = [String]() var names = Array<String>() var names: [String] = [] var names: Array<String> = [] var names: [String] = [String]() どれも内容は一緒です。 好みで使い分けてください。 よく var hoge = 0 というように型を指定せずにコンパイラに型を推論させて記述していることがあると思いますが(?)、 この書き方にすべて統一しようとすると var names = [String]() というような書き方になります。 ③ tableView.reloadData() でテーブルにデータをリロードできます。 長くなってきましたので、質問はまた別で立ててください。
mita0

2019/08/23 04:27

丁寧に教えていただきありがとうございます。 別で質問立てたのでもしお時間あればまたお願いします、
guest

0

ベストアンサー

こういうことですか?

Swift

1import UIKit 2class ViewController: UIViewController, UISearchBarDelegate, URLSessionDelegate { 3 4 var nameList: [String] = [] // まず空のstring型の配列を作る 5 6 override func viewDidLoad() { 7 ... 8 9~~~~~~~間省略 10 11 12 for value in array { 13 let value = value as! [String:Any] //より簡便な方法にしてみました 14 nameList.append(value["name"] as! String) // nameListに追加する 15 } 16 print("nameListの中身:", nameList) // 念の為、確認用に追加してみました。 17

「get()で出力したいです」を見落としてました。
fuzzballさんのいうようにどういうふうに使いたいのですか?

出力する = 返値を設定するが一般的ですが、
func get() -> [String] とすればできますが、
肝心の、get()を用いているとこで、

Swift

1 func searchBarSearchButtonClicked(_ searchBar:UISearchBar) { 2 print("検索") 3 print(searchBar.text!) 4 get() 5 }

となっているので、get()からデータが出てきても利用しておりません。

get()の中で、task.resume()としてるので、
task.resume()に渡したい? ということであれば、

resume()に(namelist: [string])として引数を持たせるか、
もしくはメンバー変数に値が既にセットされているので、
そのままresume()の中で、nameListを使えば値は引き継がれている状態になります。

さらにですが、現在の記述方法だと、task.resume()はダウンロード処理が完了前に実行されてしまうことになるので、
task.resume()内でnameListの値を用いたい場合は書き方を変える必要が出てきますよ。

投稿2019/08/22 06:15

編集2019/08/22 06:26
hameji

総合スコア1380

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

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

mita0

2019/08/22 06:38

やりたいことを追記しました。
mita0

2019/08/22 07:00

教えていただいたやり方でメンバ変数に定義できました。 本当に初心者なのでtask.resume()でtaskが動くことくらいしかtask.resume()について分かってないので少し難しいです。 var names: [String] = [] for value in array { let value = value as! Dictionary<String, Any>;() //Dictionaryに変換 //Dictionaryに変換後取り出す値の型を変換する //let values = value["name"] as! String self.names.append(value["name"] as! String) //print(values) // print(values) } print(self.names) }
hameji

2019/08/22 08:04

結局、出力したいというのは、 「コンソールにprintで表示したい」ということでしょうか???
mita0

2019/08/22 08:14

質問段階ではそういうことになります。 printで表示したいときは今後printでと記載しますね。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問