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

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

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

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

YouTube API

YouTube APIはYouTubeのビデオコンテンツと機能性をウェブサイト、アプリケーション、デバイスに統合することを可能にします。

Swift

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

Q&A

解決済

2回答

429閲覧

swiftで「Youtube Data」のJSONファイルを読み込む方法

denshatrain

総合スコア16

JSON

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

YouTube API

YouTube APIはYouTubeのビデオコンテンツと機能性をウェブサイト、アプリケーション、デバイスに統合することを可能にします。

Swift

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

0グッド

0クリップ

投稿2018/08/24 10:51

編集2018/08/26 11:50

前提・実現したいこと

「Youtube Data」のjsonファイルから動画のタイトルとURLを抜き出してitemDataArrayに追加するということをしたいです。
ネットや本を見ながらjsonの読み込みをやっていたのですがrunをするとリクエストが送信されません。

該当のソースコード

swift

1import UIKit 2import Accounts 3 4class ItemSearchResultSet: Codable { 5 var items: Items 6 7 private enum CodingKeys: String, CodingKey { 8 case items = "items" 9 } 10} 11 12class Items: Codable { 13 var id: Id 14 var snippet: Snippet 15 16 private enum CodingKeys: String, CodingKey { 17 case id = "id" 18 case snippet = "snippet" 19 } 20} 21 22class Snippet: Codable { 23 var title: Title 24 25 private enum CodingKeys: String, CodingKey { 26 case title = "title" 27 } 28} 29 30class Id: Codable { 31 var videoId: VideoId 32 private enum CodingKeys: String, CodingKey { 33 case videoId = "videoId" 34 } 35} 36 37class Title: Codable { 38 var items: [ItemData] = [ItemData]() 39 required init(from decoder: Decoder) throws { 40 let container = try decoder.container(keyedBy: CodingKeys.self) 41 let keys = container.allKeys.sorted { 42 Int($0.rawValue)! < Int($1.rawValue)! 43 } 44 for key in keys { 45 let item = try container.decode(ItemData.self, forKey: key) 46 items.append(item) 47 } 48 } 49 50 func encode(to encoder: Encoder) throws { 51 } 52 53 private enum CodingKeys: String, CodingKey { 54 case hit0 = "0" 55 case hit1 = "1" 56 case hit2 = "2" 57 case hit3 = "3" 58 case hit4 = "4" 59 case hit5 = "5" 60 case hit6 = "6" 61 case hit7 = "7" 62 case hit8 = "8" 63 case hit9 = "9" 64 case hit10 = "10" 65 case hit11 = "11" 66 case hit12 = "12" 67 case hit13 = "13" 68 case hit14 = "14" 69 case hit15 = "15" 70 case hit16 = "16" 71 case hit17 = "17" 72 case hit18 = "18" 73 case hit19 = "19" 74 case hit20 = "20" 75 } 76 77} 78 79class VideoId: Codable { 80 var items: [ItemData] = [ItemData]() 81 required init(from decoder: Decoder) throws { 82 let container = try decoder.container(keyedBy: CodingKeys.self) 83 let keys = container.allKeys.sorted { 84 Int($0.rawValue)! < Int($1.rawValue)! 85 } 86 for key in keys { 87 let item = try container.decode(ItemData.self, forKey: key) 88 items.append(item) 89 } 90 } 91 92 func encode(to encoder: Encoder) throws { 93 } 94 95 private enum CodingKeys: String, CodingKey { 96 case hit0 = "0" 97 case hit1 = "1" 98 case hit2 = "2" 99 case hit3 = "3" 100 case hit4 = "4" 101 case hit5 = "5" 102 case hit6 = "6" 103 case hit7 = "7" 104 case hit8 = "8" 105 case hit9 = "9" 106 case hit10 = "10" 107 case hit11 = "11" 108 case hit12 = "12" 109 case hit13 = "13" 110 case hit14 = "14" 111 case hit15 = "15" 112 case hit16 = "16" 113 case hit17 = "17" 114 case hit18 = "18" 115 case hit19 = "19" 116 case hit20 = "20" 117 } 118 119} 120 121class ItemData: Codable { 122 var title: String = "" 123 var videoId: String = "" 124 125 class ImageInfo: Codable { 126 private enum CodingKeys: String, CodingKey { 127 case medium = "Medium" 128 } 129 var medium: String? 130 } 131 132 var imageInfo : ImageInfo = ImageInfo() 133 134 private enum CodingKeys: String, CodingKey { 135 case title = "title" 136 case videoId = "videoId" 137 } 138 139} 140 141 142 143class ViewController: UIViewController , UISearchBarDelegate { 144 145 @IBOutlet var searchBar: UISearchBar! 146 147 var itemDataArray = [ItemData]() 148 149 let appid = "AIzaSyCAIznRo4MUdgBtijMnd2De9YEUqMdmwaY" 150 151 let entryUrl: String = "https://www.googleapis.com/youtube/v3/search?key=AIzaSyCAIznRo4MUdgBtijMnd2De9YEUqMdmwaY&q=" 152 153 override func viewDidLoad() { 154 super.viewDidLoad() 155 // Do any additional setup after loading the view, typically from a nib. 156 157 searchBar.placeholder = "ここに入力してください" 158 searchBar.delegate = self 159 } 160 161 override func didReceiveMemoryWarning() { 162 super.didReceiveMemoryWarning() 163 // Dispose of any resources that can be recreated. 164 } 165 166 func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { 167 168 print("検索ボタンがタップされました!") 169 170 guard let inputText = searchBar.text else { 171 return 172 } 173 174 guard inputText.lengthOfBytes(using: String.Encoding.utf8) > 0 else { 175 return 176 } 177 178 itemDataArray.removeAll() 179 180 181 182 let parameter = ["appid": appid, "query": inputText] 183 184 let requestUrl = entryUrl + inputText + "&part=snippet&maxResults=10&order=viewCount" 185 186 request(requestUrl: requestUrl) 187 188 searchBar.resignFirstResponder() 189 } 190 191 func encodeParamater(key: String, value: String) -> String? { 192 guard let escapedValue = value.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) else { 193 return nil 194 } 195 196 return "(key) = (escapedValue)" 197 198 } 199 200 func createRequestUrl(parameter:[String: String]) -> String { 201 var parameterString = "" 202 for key in parameter.keys { 203 guard let value = parameter[key]else { 204 continue 205 } 206 207 if parameterString.lengthOfBytes(using: String.Encoding.utf8) > 0 { 208 parameterString += "&" 209 } 210 211 guard let encodeValue = encodeParamater(key: key, value: value) else { 212 continue 213 } 214 215 parameterString += encodeValue 216 217 } 218 let requestUrl = entryUrl + "?" + parameterString 219 print(requestUrl) 220 return requestUrl 221 } 222 223 func request(requestUrl: String) { 224 print(1) 225 guard let url = URL(string: requestUrl) else { 226 return 227 } 228 let request = URLRequest(url: url) 229 let session = URLSession.shared 230 let task = session.dataTask (with: request) { (data:Data?, response:URLResponse?, error:Error?) in 231 guard error == nil else { 232 let alert = UIAlertController(title: "エラー", message: error?.localizedDescription, preferredStyle: .alert) 233 DispatchQueue.main.async { 234 self.present(alert, animated: true, completion: nil) 235 } 236 return 237 } 238 239 guard let data = data else { 240 return 241 } 242 243 do { 244 let resultSet = try JSONDecoder().decode(ItemSearchResultSet.self, from: data) 245 246 self.itemDataArray.append(contentsOf: resultSet.items.id.videoId.items) 247 self.itemDataArray.append(contentsOf: resultSet.items.snippet.title.items) 248 print("データーが追加されました") 249 print(self.itemDataArray) 250 } catch let error { 251 print("## error: (error)") 252 } 253 254 DispatchQueue.main.async { 255 256 } 257 258 } 259 260 261 262 task.resume() 263 264 } 265 266 267} 268

困っている点

上の

swift

1func request(requestUrl: String) { 2 print(1) 3 guard let url = URL(string: requestUrl) else { 4 return 5 } 6 //ここから呼び出されていない 7 let request = URLRequest(url: url) 8 let session = URLSession.shared 9 let task = session.dataTask (with: request) { (data:Data?, response:URLResponse?, error:Error?) in 10 guard error == nil else { 11 let alert = UIAlertController(title: "エラー", message: error?.localizedDescription, preferredStyle: .alert) 12 DispatchQueue.main.async { 13 self.present(alert, animated: true, completion: nil) 14 } 15 return 16 } 17 18 guard let data = data else { 19 return 20 } 21 22 do { 23 let resultSet = try JSONDecoder().decode(ItemSearchResultSet.self, from: data) 24 25 self.itemDataArray.append(contentsOf: resultSet.items.id.videoId.items) 26 self.itemDataArray.append(contentsOf: resultSet.items.snippet.title.items) 27 print("データーが追加されました") 28 print(self.itemDataArray) 29 } catch let error { 30 print("## error: (error)") 31 } 32 33 DispatchQueue.main.async { 34 35 } 36 37 } 38 39 40 41 task.resume() 42 43 }

この部分がキーボードの検索ボタンを押したときに呼び出されてはいるようなのですが上に書いたところでprint文が呼び出されなくないました。その後にもitemDataArrayにデーターが入っていません。またprintするとコンソールに[]と表示されます。

また、実機でも試しましたができませんでした。

補足情報(FW/ツールのバージョンなど)

swift4.1
ios11.4

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

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

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

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

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

nakasho_dev

2018/08/24 16:48

Print文を埋め込んでいるところを見ると、ご自身でもデバッグされていると思うのですが、どこまでは処理が走っているかなどの現状の認識を追加されると回答がされやすいかと思います。
guest

回答2

0

ベストアンサー

Swift

1func request(requestUrl: String) { 2 print(1) 3 guard let url = URL(string: requestUrl) else { 4 return 5 } 6 //ここから呼び出されていない 7 let request = URLRequest(url: url)

とのことなのでURL(string: requestUrl)の結果がnilなのでしょう。
他の方が指摘している通りなのですがcreateRequestUrlやencodeParamaterは使用されていないようですのでrequestUrlを生成する直前にエスケープしてあげるような以下の方法ではいかがでしょうか。

Swift

1guard let escapedInputText = inputText.addingPercentEncoding( 2 withAllowedCharacters: CharacterSet.urlQueryAllowed 3) else { 4 return 5} 6let requestUrl = entryUrl + escapedInputText + "&part=snippet&maxResults=10&order=viewCount"

guardでnilチェックする際はelseブロック内でログを出力するようにしておくと、バグに気付きやすくなります。

投稿2018/09/03 10:03

nakasho_dev

総合スコア2655

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

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

0

searchBarSearchButtonClicked(_:)inputTextがURLエンコードされてないですね。

投稿2018/08/26 02:23

MasakiHori

総合スコア3384

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

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

denshatrain

2018/08/26 20:38

どういうふうにURLエンコードをしたら良いですか?
_lemon2003_

2018/08/26 23:34 編集

encodeURIComponent() ですね。 返り値がエンコードされた文字列になります。
MasakiHori

2018/08/27 01:48

あなたが使用している addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) でいいです
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問