昨日、ここの優秀な方に見てもらったのですが、私の理解が及ばず解決に至っていない問題について質問を立て直しました。お力を借りることはできますでしょうか?
【過去質問】 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(結果表示)
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。