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

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

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

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

Swift

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

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

解決済

1回答

773閲覧

【Swift】for文を使用してAPIを叩く方法

duck015

総合スコア29

iOS

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

Swift

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

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

0グッド

0クリップ

投稿2020/02/11 10:24

編集2020/02/11 10:26

前提・実現したいこと

tertailのAPIを叩き、質問一覧をTableViewに表示させたいです(Alamofire SwiftyJSONを使用)。
現状、teratailの質問のIDをFirestoreに下図の通り配列として保存しています。
今回はこの配列からIDを取り出し、各質問の詳細を表示させたいです。
イメージ説明

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

まずFirestoreからデータを取り出し、それをfor文を用いて表示させようと考えています。
しかしこのコードですと、配列から取り出した最後のIDの質問しか表示させることができない状況です。

考え方としては、for文でIDを取り出したら、都度APIを叩いてデータを取得するという流れになると思うのですが、それをうまくコードに落とし込むことができず苦慮しております。
恐れ入りますが、解決策をご教示いただけませんでしょうか?

該当のソースコード

func fetchFavoriteQuestions() { print("favfecth") if let myId = Auth.auth().currentUser?.uid { let userRef = Firestore.firestore().collection("users").document(myId) userRef.getDocument { (snap, error) in if let error = error{ print("Error getting question ID") } else { guard let data = snap?.data()?["likes"] as? [Int] else { return } for likesArray in data { print("https://teratail.com/api/v1/questions/(likesArray)") Alamofire.request("https://teratail.com/api/v1/questions/(likesArray)").responseJSON { response in self.questions = [] guard let object = response.result.value else { return } let json = JSON(object) let id = json["question"]["id"].intValue let title = json["question"]["title"].stringValue let tags = json["question"]["tags"].arrayObject let displayName = json["question"]["user"]["display_name"].stringValue let photo = json["question"]["user"]["photo"].stringValue let created = json["question"]["created"].stringValue let isAccepted = json["question"]["is_accepted"].boolValue self.questions.append(QuestionEntity(id: id, title: title, tags: tags as? [String] ?? [], displayName: displayName, photo: photo, created: created, isAccepted: isAccepted)) print(self.questions) self.notify() print("通知") } } } } } }

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

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

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

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

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

hoshi-takanori

2020/02/11 10:34

それだと API を叩きすぎになるので、端末側である程度キャッシュするとかしたほうがいいと思う…。
hoshi-takanori

2020/02/11 10:39

あと、Firebase を使う意味もよく分からないし。闇雲にコーディングを頑張るより、一度立ち止まってアプリ全体の設計を考える必要があるのでは?
takabosoft

2020/02/12 02:10

teratailのapiよくしらないのですが、質問IDを複数渡して、複数結果をもらえるAPIは存在しないんですかね?
eytyet

2020/02/12 08:47

質問詳細はひとつずつしか取れないみたいですね。回数制限も厳しいようです。 ところで、self.notify()は複数回呼ばれ、コンソールには複数の質問が出力されているのではありませんか?そうであれば、tableView側の実装の問題なので、そちらのコードを示していただけますでしょうか。
duck015

2020/02/12 13:40

皆様アドバイスいただきありがとうございます。 ひとまずfor文で取り出したIDを引数にとる関数を作成することにより解決しました。 ただ、hoshi-takanori様のおっしゃる通りAPI叩き過ぎになるので、並行して別の方法も考えたいと思います。 回数制限も厳しいので...。
hoshi-takanori

2020/02/12 17:41

やっぱり Firestore を使ってる理由が気になるんですが、もしかして単なる便利なデータの保存場所(他をご存知ない)だと思ってませんか? ソース一式 github かどこかに上げてくれたら見てみますけど…。
duck015

2020/02/13 08:16 編集

ありがとうございます、是非見ていただきたいです…。下記になります。 Firestoreを使っている理由は、前に使ったことあるからくらいで、たしかにおっしゃる通り便利なデータ保存場所くらいの認識になってるのが現状です…。 ちなみにFirestoreで保存予定のデータは下記です。それほどデータ量は多くないかと思います。 ・お気に入り質問ID ・検索履歴
hoshi-takanori

2020/02/13 05:33

ソースありがとうございます。動かしてみたところ、思ってたより本格的でびっくりしました。ソースはまだ見てませんが、いくつか質問があるので、github の issue に書きます。
guest

回答1

0

自己解決

ひとまず下記関数の引数に取り出したIDを入れることにより実装しました。
APIにアクセスする回数制限があるので、別途別の方法も考えたいと思います。

func fetchQuestion(id: Int) { Alamofire.request("https://teratail.com/api/v1/questions/(id)").responseJSON { response in guard let object = response.result.value else { return } let json = JSON(object) let id = json["question"]["id"].intValue let title = json["question"]["title"].stringValue let tags = json["question"]["tags"].arrayObject let displayName = json["question"]["user"]["display_name"].stringValue let photo = json["question"]["user"]["photo"].stringValue let created = json["question"]["created"].stringValue let isAccepted = json["question"]["is_accepted"].boolValue self.questions.append(QuestionEntity(id: id, title: title, tags: tags as? [String] ?? [], displayName: displayName, photo: photo, created: created, isAccepted: isAccepted)) print(self.questions) self.notify() print("通知") } }

投稿2020/02/12 13:43

編集2020/02/12 13:44
duck015

総合スコア29

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問