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

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

新規登録して質問してみよう
ただいま回答率
85.37%
非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Swift

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

クロージャ

クロージャは、プログラミング言語における関数オブジェクトの一種です。 引数以外の変数を実行時の環境ではなく、 自身が定義された環境において解決することを特徴とします。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

API

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

Q&A

解決済

2回答

2925閲覧

Swift クロージャによる画面遷移と値の渡し方について

nyansuke373

総合スコア7

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Swift

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

クロージャ

クロージャは、プログラミング言語における関数オブジェクトの一種です。 引数以外の変数を実行時の環境ではなく、 自身が定義された環境において解決することを特徴とします。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

API

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

0グッド

0クリップ

投稿2020/05/08 01:27

昨日、ここの優秀な方に見てもらったのですが、私の理解が及ばず解決に至っていない問題について質問を立て直しました。お力を借りることはできますでしょうか?
【過去質問】 https://teratail.com/questions/259406
【今やっている事】
ふりがな変換APIを利用したアプリ開発
【どうやっているか】
ViewController(入力後HttpRequestを呼んでいます)→HttpRequest(API取得)→ResultViewController(結果表示)を考えています。
【解決したい事】
下記コードで実行してもAlamofire.requestのところでその中の処理が流れずに、segueを使って値渡しをしてしまうため、結果が表示されるResultViewControllerにnilが渡されてしまいエラーが起こってしまう
【期待値】
Alamofire.requestの処理が通ってからResultViewControllerに値を渡してresultTextViewに表示すること

不明な点などがあれば、追記いたします。よろしくお願いいたします。

Swift

1import UIKit 2import Alamofire 3import SwiftyJSON 4 5class ViewController: UIViewController,UITextFieldDelegate { 6 7 @IBOutlet weak var inputTextView: UITextField! 8 9 // APIRequestの初期化 10 var apiRequest = APIRequest() 11 12 override func viewDidLoad() { 13 super.viewDidLoad() 14 15 inputTextView.delegate = self 16 initInputText() 17 } 18 19 private func initInputText() { 20 inputTextView.text = "" 21 } 22 23 @IBAction func convertButton(_ sender: UIButton) { 24 //キーボードを閉じる 25 view.endEditing(true) 26 27 28 // リクエストを渡す時にクロージャも渡し、その内部で書き換えの処理を行う 29 // クロージャの処理は completion: の後の {} の中 30 apiRequest.HttpRequest(sentence: inputTextView.text!, completion: { 31 result in 32 // navigationController を使った画面遷移は、performSegue もしくは instantinateViewController と pushViewController を組み合わせて使う 33 34 // segue を使う画面遷移 35 self.performSegue(withIdentifier: "nextSegue", sender: result) 36 }) 37 } 38 39 // segue を使って値渡しする場合 40 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 41 // 遷移先が ResultViewController の場合 42 if let nextVC = segue.destination as? ResultViewController { 43 // sender が String としてダウンキャストできる場合 44 if let result = sender as? String { 45 // 遷移先のプロパティに値をセットする 46 nextVC.result = result 47 } 48 } 49 } 50} 51 52public class APIRequest { 53 // 関数の引数としてクロージャを取るように設定し、クロージャ内部で目的とするビューに表示させる 54 // クロージャは completion: の後に引数として取る 55 // func HttpRequest(sentence: String) { 56 func HttpRequest(sentence: String, completion: @escaping (String) -> Void ) { 57 let url = URL(string: "https://labs.goo.ne.jp/api/hiragana")! 58 let parameters = ["app_id":"適切なAPIキー https://labs.goo.ne.jp/api/jp/hiragana-translation/ で発行後、入力してください", 59 "sentence":"(sentence)", 60 "output_type":"hiragana"] 61    //AlamofireでHTTPリクエスト 62 Alamofire.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseJSON { response in 63       //↓ここに処理が流れない 64 switch response.result { 65 // 処理成功時 66 case .success(let data): 67 if let result = data as? [String: Any] { 68 //SwiftyJSONを使用してJSON解析 69 let json = JSON(result as Any) 70 let resultString = json["converted"].string 71 // MARK: 変更 72 // ResultVC.showResult(resultString: resultString!) 73 // 上記の方法でビューをインスタンス化しても表示することはできない。 74 // インスタンス化する方法はクロージャで渡された処理に任せる 75 if let resultString = resultString { 76 // クロージャで渡された処理がメインキューで行うべき処理かもしれないので、メインキューで処理する 77 DispatchQueue.main.async { 78 // クロージャの処理 79 completion(resultString) 80 } 81 } 82 83 } 84 // 処理失敗時 85 case .failure(let error): 86 print("error: ", error.localizedDescription) 87 } 88 } 89 } 90} 91 92class ResultViewController: UIViewController, UITextFieldDelegate { 93 // MARK: 追加 94 // 前の画面から渡される変数 95 var result: String! 96 97 @IBOutlet weak var resultTextView: UITextField! 98 99 override func viewDidLoad() { 100 super.viewDidLoad() 101 resultTextView.delegate = self 102 103 // ここで showResult を実行する 現在ここにnilが渡ってきてしまっています。 104 showResult(resultString: result) 105 } 106 107 func showResult(resultString: String) { 108 resultTextView?.text = resultString 109 print(resultString) 110 } 111} 112

ViewController(入力後HttpRequestを呼んでいます)→HttpRequest(裏でAPI取得)→ResultViewController(結果表示)
ストーリーボード

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

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

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

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

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

guest

回答2

0

ベストアンサー

ViewController からではなく、ボタンからSegueを張ったのが原因だと思います。

ボタンにSegueを関連づけると、ボタンを押した瞬間に、Segueで関連付けられたViewControllerなどが立ち上がりますが、そうするとprepareなどの処理は呼ばれなくなり、結果今回のようなエラーがでます。

いまあるSegueを削除し、下記のリンクを参考にViewControllerからSegueを張ってもらえますでしょうか。

この記事の「1. ViewController同士をSegueで繋ぐ」の動画に従ってSegueを張り、次に「2. Segueにidentifierをつける」に従ってSegueにIdentifier(今回の場合はnextSegue)を設定してみてください。

投稿2020/05/08 05:09

TsukubaDepot

総合スコア5086

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

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

0

ViewController側で通信の結果を受けるプロパティを宣言して
var result: String = ""

クロージャの中で結果の文字列を代入してperform関数呼べば行けないですか?

apiRequest.HttpRequest(sentence: inputTextView.text!, completion: { result in self.result = result self.performSegue(withIdentifier: "nextSegue", sender: nil) // nilに変更 })

prepare関数も少し変更

override func prepare(for segue: UIStoryboardSegue, sender: Any?) { // 遷移先が ResultViewController の場合 if let nextVC = segue.destination as? ResultViewController { // 遷移先のプロパティに値をセットする nextVC.result = self.result } }

投稿2020/05/08 02:51

TakuyaAso

総合スコア1361

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問