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

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

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

mBaaSとはモバイルアプリケーションでの利用に特化したBaaSです。スマートフォン向けのWebアプリケーションが必要とするサーバ側の様々な機能をインターネットを通じてサービスとして提供しています。

Xcode

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

Swift

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

Q&A

解決済

1回答

1210閲覧

findObjectsInBackgroundで取得した値をreturnしたい

退会済みユーザー

退会済みユーザー

総合スコア0

mBaaS

mBaaSとはモバイルアプリケーションでの利用に特化したBaaSです。スマートフォン向けのWebアプリケーションが必要とするサーバ側の様々な機能をインターネットを通じてサービスとして提供しています。

Xcode

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

Swift

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

0グッド

0クリップ

投稿2020/05/22 06:13

前提・実現したいこと

mBaaSを用いて,
取得してきた値から,辞書のキーをreturnさせたいです.

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

swift

1Unexpected non-void return value in void function

該当のソースコード

swift

1func hoge( ) -> Array<Int>{ 2 var ans : Array<Int> = [0] 3 var result: [NCMBObject] = [] 4 5 query?.findObjectsInBackground({(objects, error) in 6 if (error != nil){ 7 // 検索失敗時の処理 8 return ans[0] = 0 //① 9 }else{ 10 // 検索成功時の処理 11 result = objects! as! [NCMBObject] 12 //検索結果の1番目のnumを格納 13 let num = result[0].object(forKey: "num") as! Int 14 //ansにdictionaryのnumの値が入ったキーを格納 15 ans = Array(dictionary.filter {$0.value == num}.keys) 16 17 print("KEY=", Array(dictionary.filter {$0.value == similarColor}.keys)) 18 19 return ans //② ここでエラー 20 } 21 22 }) 23//③ 24}

試したこと

最初,①と②のところでエラーが出ていました.

そこで,①と②のところにreturnを書きました.
①のエラーは消えたのですが,②のエラーは出たままです.

こちらで,クロージャー内のみでは
駄目というところまではわかりましたが,③のところにreturnを書くと
格納される前にreturnが行われてしまいます.

②の値をreturnさせるためにはどのようにしたら良いのでしょうか??

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

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

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

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

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

guest

回答1

0

ベストアンサー

クロージャ内部での処理は非同期な上、ご推察のように戻り値とし値を返すことはできないため、何らかの処理が必要になります。

(1)や(2)にreturnを置いたときに出たエラーは、findObjectsInBackgroundに渡すクロージャが引数2つを取り、Voidを返す(言い換えれば戻り値がない)クロージャとして定義されているため、戻り値の型が合わないという意味のエラーです。

一般的なのは非同期処理させたい関数にクロージャを渡し、データ取得が完了した段階でそのクロージャを実行させる方法です。

今回のコードだとこんな感じになると思います。
UIパーツを更新するなど、一部の処理においては completion()をさらにメインスレッドで実行する必要があります。

Swift

1func hoge(flag: Bool, completion: @escaping (Array<Int>) -> Void) { 2 var ans : Array<Int> = [0] 3 4 // query?.findObjectsInBackground を呼び出したつもり 5 // 1秒後にクロージャの中が実行される 6 DispatchQueue.main.asyncAfter(deadline: .now() + 1.0 ) { 7 if flag == false { 8 // 失敗した場合 9 ans[0] = 0 10 // return するのではなく、completion で指定されたクロージャを実行する 11 completion(ans) 12 } else { 13 // 成功した場合 14 ans[0] = 1 15 completion(ans) 16 } 17 } 18} 19 20// 一つ目の引数はテスト用の引数。 21// 二つ目の引数で指定したクロージャが hoge() の中で(completionとして)実行される 22hoge(flag: true, completion: { data in 23 // 単に行に分けて表示しているだけ。実際には具体的な処理を記述する 24 for row in data { 25 print(row) 26 } 27})

(3)の部分に return を置き、ここで値を返すこともできなくはありません。セマフォを使いロックをかければ実現可能ですが、不用意に処理を止めることは推奨されませんのでここでは触れないでおきます。

投稿2020/05/22 06:43

TsukubaDepot

総合スコア5086

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

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

退会済みユーザー

退会済みユーザー

2020/05/26 14:15

ありがとうございます!! ご指摘の通りに書き直したら思い通りの動作 ができました. クロージャについては素人なもので どうしても理解が足りず本当に困っていたので 助かりました. ありがとうございました!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問