2017-02-03 9 views
0

私はSwiftに若干新しく、このサイトの助けを借りて補完ハンドラを使用する方法をほとんど考え出しました。数日後にこれを動作させると、より直接的な助けに感謝します。 XUserAPIResult構造体を返すレスポンスを解釈する前に、この関数が完了していることを確認するにはどうすればよいですか?

func storeRegistrationInfo(registrant: XRegistrantInfo, finished: @escaping (XUserAPIResult)->()) { 
    var apiResult = XUserAPIResult() 

    let appDelegate = UIApplication.shared.delegate as! AppDelegate 

    let context = appDelegate.persistentContainer.viewContext 

    let newRegistrant = NSEntityDescription.insertNewObject(forEntityName: "User", into: context) 

    let requestURL = NSURL(string: USER_API_URL) 
    let request = NSMutableURLRequest(url: requestURL! as URL) 

    request.httpMethod = "POST" 

    newRegistrant.setValue(registrant.firstName, forKey: "firstName") 
    newRegistrant.setValue(registrant.lastName, forKey: "lastName") 
    newRegistrant.setValue(registrant.zipCode, forKey: "zipCode") 
    newRegistrant.setValue(registrant.emailAddress, forKey: "emailAddress") 
    newRegistrant.setValue(registrant.password, forKey: "password") 
    newRegistrant.setValue(registrant.personna, forKey: "personna") 
    do{ 
     try context.save() 
     let postParameters = "tag=" + REGISTRATION_API_TAG + "&firstName=" + registrant.firstName + "&lastName=" + registrant.lastName + "&password=" + registrant.password + "&username=" + registrant.emailAddress + "&personna=" + registrant.personna + "&zipCode=" + registrant.zipCode 
     request.httpBody = postParameters.data(using: .utf8) 
     let task = URLSession.shared.dataTask(with: request as URLRequest){ 
      data, response, error in 

      if error != nil{ 
       print("error is \(error)") 
       return 
      } 

      print("response = \(response)") 
      //parsing the response 
      do { 
       //converting resonse to NSDictionary 
       let myJSON = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary 

       //parse json 2 

       if let dictionary = myJSON as? [String: Any]{ 
        if let apiSuccess = dictionary["success"] as? Int{ 
         apiResult.success = apiSuccess 
        } 
        if let apiError = dictionary["error"] as? Int{ 
         apiResult.error = apiError 
         if apiError != 0{ 
          if let apiErrorMessage = dictionary["error_msg"] as? String{ 
           apiResult.errorMessage = apiErrorMessage 
          } 

         }else{ 
          if let apiUID = dictionary["uid"] as? String{ 
           apiResult.uniqueID = apiUID 
          } 
          if let nestedDictionary = dictionary["user"] as? [String: Any]{ 
           if let apiFirstName = nestedDictionary["firstName"] as? String{ 
            apiResult.user.firstName = apiFirstName 
           } 
           if let apiLastName = nestedDictionary["lastName"] as? String{ 
            apiResult.user.lastName = apiLastName 
           } 
           if let apiEmail = nestedDictionary["e-mail"] as? String{ 
            apiResult.user.emailAddress = apiEmail 
           } 
           if let apiCreatedAt = nestedDictionary["created_at"] as? String{ 
            apiResult.user.createdAt = apiCreatedAt 
           } 
           if let apiPersonna = nestedDictionary["personna"] as? String{ 
            apiResult.user.personna = apiPersonna 
           } 
          } 
          finished(apiResult) 
         } 
        } 
       } 
      } catch { 
       print(error) 
      } 
     } 
     task.resume() 
     finished(apiResult) 
    } catch { 
     print("There was an error saving to Core Data") 
     finished(apiResult) 
    } 
} 

submitRegistrationButton()コードはstoreRegistrationInfo(まで待つことになっている):

@IBAction func submitRegistrationButton(_ sender: Any) { 

    if((firstNameField.text?.trimmingCharacters(in: .whitespacesAndNewlines).characters.count) == 0){ 
     showXAlert(title: "Oops!", message: "Please enter your first name.", viewController: self) 
    }else if((lastNameField.text?.trimmingCharacters(in: .whitespacesAndNewlines).characters.count) == 0){ 
      showXAlert(title: "Oops!", message: "Please enter your last name.", viewController: self) 
     }else if((emailAddressField.text?.trimmingCharacters(in: .whitespacesAndNewlines).characters.count) == 0){ 
       showXAlert(title: "Oops!", message: "Please enter your email address.", viewController: self) 
      }else if !isValidEmail(testStr: emailAddressField.text!){ 
        showXAlert(title: "Oops!", message: "Please enter a valid email address.", viewController: self) 
       }else if((passwordField.text?.trimmingCharacters(in: .whitespacesAndNewlines).characters.count) == 0){ 
        showXAlert(title: "Oops!", message: "Please enter a password.", viewController: self) 
        }else if passwordField.text != passwordConfirmationField.text{ 
         showXAlert(title: "Oops!", message: "Your password and password confirmation do not match. Please correct.", viewController: self) 
       }else{ 
        registrant.firstName = firstNameField.text! 
        registrant.lastName = lastNameField.text! 
        registrant.zipCode = zipCodeField.text! 
        registrant.emailAddress = emailAddressField.text! 
        registrant.password = passwordField.text! 
        storeRegistrationInfo(registrant: registrant) { (object: XUserAPIResult) in 

         print("submissionStatus = \(object.success)") 

         if object.success == 1 { 
          showXAlert(title: "Welcome \(self.registrant.firstName)!", message: "Your registration was submitted successfully. Log in by clicking the Login button below", viewController: self) 
         }else{ 
         showXAlert(title: "Un Oh", message: "There was a problem with your registration. \(object.errorMessage)", viewController: self) 
         } 

        } 
       } 
} 

...呼び出すこと:私が持っている

を入力し、に基づいて適切なアラートを表示します。XUserAPIResult's成功プロパティ。

問題は、成功チェックコードが実行されてからstoreRegistrationInfo()がJSONの解析を完了する前に実行されていることです。間違ったアラートを表示し、JSONが解析された後に正しく実行されます。コードの他の側面(Web API呼び出し、JSONの解析、Webデータベースへのデータの保存)は機能します。

私は、補完ハンドラの使用方法やstoreRegistrationInfo()の呼び出し方法に問題がありますが、修正方法はわかりません。:JSONを解析された後

storeRegistrationInfo(registrant: registrant) { (object: XUserAPIResult) in 

    print("submissionStatus = \(object.success)") 

    if object.success == 1 { 
     showXAlert(title: "Welcome \(self.registrant.firstName)!", message: "Your registration was submitted successfully. Log in by clicking the Login button below", viewController: self) 
    }else{ 
     showXAlert(title: "Un Oh", message: "There was a problem with your registration. \(object.errorMessage)", viewController: self) 
    }  
} 

...だけと呼ばれ、UserAPIResult構造体は次のとおりです。

は、どのように私は@IBActionのFUNCのsubmitRegistrationButtonでアラートコード(どれ_送信者が)ことを確認してください人口は移住し、戻った?

ありがとうございました。

答えて

0

として問題になりますが、ここでラインです:

task.resume() 
finished(apiResult) 

あなたはへの呼び出しを削除する必要がありますfinished補完ハンドラは、それがすでにplacされている場所で呼び出される必要があるためですエド、応答を得た後。

フィールド検証コードを簡略化してguard文を使用することをお勧めします。

+0

ありがとう!それはそれを修正したようだ!私はガードステートメントに関するあなたの助言に従います... – Wayne

+0

...「ようこそ...」アラートが表示された後、アプリケーションがクラッシュしているため、上記のように表示されます。これが関連しているかどうかはわかりません。 – Wayne

+0

この問題と、同じ問題に遭遇した他の人のために、[this thread](http://stackoverflow.com/questions/37801370/how-do-i-dispatch-sync-dispatch-async-dispatch)のおかげで-after-etc-in-swift-3) 'showXAlert()'が主なスレッド以外のスレッドから警告を提示しようとしていることに気付きました。これがクラッシュを引き起こしていたものです。 – Wayne

0

typealias CompletionHandler = (data:XRegistrantInfo,success:Bool) -> Void; 


func storeRegistrationInfo(registrant: XRegistrantInfo,completionHandler: CompletionHandler) { 
    // your code. 
    // 
    // 
    completionHandler(data: dataToReturn,success : true/false) 
} 

を試してみて、コールがあなたのコードで

storeRegistrationInfo(registrant, { (data,success) -> Void in 
    //onCompletion the code will go here 
    if success { 
     // success 
    } else { 
     // fail 
    } 
}) 
+0

ありがとうございました。私はちょうど 'typealias'について簡単な研究をしました。コードの保守性/可読性を向上させるためにこれを提案していますか? '成功:Bool'と私が現在持っているように、XUserAPIResultインスタンスの' success:Int'プロパティをチェックする何らかの理由はありますか? – Wayne

+0

戻り値の型が2つの値の間で切り替わる場合は、通常はboolを使用することをお勧めします。シーケンスよりも多い場合はenum – Moin

関連する問題