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

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

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

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

Swift 2

Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

Q&A

解決済

1回答

9813閲覧

処理の完了を待ってから次の処理を行いたい

退会済みユーザー

退会済みユーザー

総合スコア0

Swift

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

Swift 2

Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

0グッド

0クリップ

投稿2018/01/06 07:53

編集2018/01/06 08:38

###前提・実現したいこと
iOSアプリケーションの改造をしています。
apiから値を取得しにいくうちに画面が進んでしまい、別の処理が動いてしまいます。
取得した値によって処理を変えたいのですが、同期・非同期の処理をどのようにいれるのが
正しい(というか一般的?)のかがわかりません。
普通はこのようにするものだ、というものがありましたら教えていただきたいです。

###該当のソースコード

swift

1AppDelegate.swift 2 3func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool { 4 //apiからデータを取得する 5 //ここで行う処理を待ってから次へ行きたい 6   getMemberInfo() 7   8 //取得したデータをもとに処理を行う 9 ... 10 11 //データ取得する前にhogeViewControllerの中の処理が動いてしまう 12 window?.rootViewController = hogeViewController 13} 14 15func getMemberInfo(){ 16 //共通で使うAPI呼び出し部分 17 let ret: [AnyHashable: Any]? = getInfo(data1, data2) 18 19 //取得に失敗するときはサーバがおちてる 20 if ( ret == nil ){ 21 DispatchQueue.main.async { 22 let alertController = UIAlertController(title: "Error",message: "データとれませんでした.再起動してください", preferredStyle: UIAlertControllerStyle.alert) 23 let okAction = UIAlertAction(title: "アプリを閉じる", style: UIAlertActionStyle.default){ (action: UIAlertAction) in 24 exit(0) 25 } 26 alertController.addAction(okAction) 27 self.window?.rootViewController?.present(alertController,animated: true,completion: nil) 28 } 29 return  30 }else{ 31 //データがとれたらUserDefaultとかに保存する処理 3233 } 34} 35 36Utility.swift 37 func getInfo(_ data1: String, whithdata2 data2: String) -> [AnyHashable: Any]? { 38 //リクエスト用のパラメータを設定 39 var url: String = "http://~" 40 let param: String = "data1=" + data1 + "&data2=" + data2 41 42 let condition = NSCondition() 43 var parsedData: [AnyHashable : Any]? = nil 44 var encURL: NSURL = NSURL() 45 46 encURL = NSURL(string:url.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)!)! 47 var r = URLRequest(url: encURL as URL, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 20) 48 r.httpMethod = "POST" 49 r.httpBody = param.data(using: String.Encoding.utf8) 50 51 let task = URLSession.shared.dataTask(with: r) { (data, response, error) in 52 if error == nil { 53 do { 54 if error != nil { 55 condition.unlock() 56 } 57 let httpResponse: HTTPURLResponse? = (response as? HTTPURLResponse) 58 //200が成功 59 if httpResponse?.statusCode != 200 { 60 condition.unlock() 61 } 62 parsedData = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [AnyHashable : Any] 63 } catch let error as NSError { 64 condition.unlock() 65 } 66 } 67 condition.signal() 68 condition.unlock() 69 } 70 condition.lock() 71 task.resume() 72 73 condition.wait() 74 condition.unlock() 75 76 return parsedData 77 } 78 79

###補足情報(言語/FW/ツール等のバージョンなど)
Xcode9.1
Swift3

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

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

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

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

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

guest

回答1

0

ベストアンサー

データを取得する前に次の処理に行ってしまうと思っていたのですが、

func getMemberInfo(){ //共通で使うAPI呼び出し部分 let ret: [AnyHashable: Any]? = getInfo(data1, data2) //取得に失敗するときはサーバがおちてる if ( ret == nil ){ DispatchQueue.main.async { let alertController = UIAlertController(title: "Error",message: "データとれませんでした.再起動してください", preferredStyle: UIAlertControllerStyle.alert) let okAction = UIAlertAction(title: "アプリを閉じる", style: UIAlertActionStyle.default){ (action: UIAlertAction) in exit(0) } alertController.addAction(okAction) self.window?.rootViewController?.present(alertController,animated: true,completion: nil) } return  }else{ //データがとれたらUserDefaultとかに保存する処理 … } }

このDispatchQueue.main.asyncで囲って非同期でアラートを表示していたことで次へ進んでいました。
ですので、getMemberInfo()に返り値を持たせて呼び出し側でアラートを表示するようにしました。

func getMemberInfo() -> Bool { var ret_bool: Bool = false //共通で使うAPI呼び出し部分 let ret: [AnyHashable: Any]? = getInfo(data1, data2) //取得に失敗するときはサーバがおちてる if ( ret == nil ){ ret_bool = false } else { ret_bool = true //いろんな処理 ... } return ret_bool } //呼び出し側 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool { var ret: Bool = false //apiからデータを取得する ret = getMemberInfo() if ret == true { //取得したデータをもとに処理を行う ... window?.rootViewController = hogeViewController() } else { window?.rootViewController = UIViewController() let alertController = UIAlertController(title: "Error",message: "データとれませんでした.再起動してください", preferredStyle: UIAlertControllerStyle.alert) let okAction = UIAlertAction(title: "アプリを閉じる", style: UIAlertActionStyle.default){ (action: UIAlertAction) in exit(0) } alertController.addAction(okAction) self.window?.rootViewController?.present(alertController,animated: true,completion: nil) } return true }

アラートはrootViewControllerが設定されていないと表示できませんでしたので、このようにすることで表示できるようになりました。
もっとうまいやり方があるような気がしますが、これでやりたい動きになりました。

いろいろごっちゃになっていて、質問も抽象的になってしまいましたが、自己解決とさせていただきます。

投稿2018/01/07 09:00

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問