2017-08-29 28 views
-1

我试图建立一个用户regeistration窗体,它应该检查用户是否已经存在。所以我发送一个php请求到我的mysql服务器。如果返回值为空,则用户尚未存在。如何等待下载任务快速完成3

Unfortunatley我真的坚持等待这个检查完成。我尝试了几个解决方案,我发现谷歌,但没有一个工作。我当前的代码使用信号量,并将崩溃“致命错误:意外地发现零,而解包可选值”,所以信号量不会等待,直到任务完成,因为我期望它。

任何提示,将不胜感激。多谢你们。

private func isUniqueEmail(email: String) -> Bool { 
    var result: Bool? 
    let semaphore = DispatchSemaphore(value: 1) 
    let requestURL = URL(string: "http://localhost/firstpostget/functions/get.php") 
    var request = URLRequest(url: requestURL!) 
    request.httpMethod = "POST" 
    let postParameters = "email=" + email 
    request.httpBody = postParameters.data(using: .utf8) 
    let configuration = URLSessionConfiguration.default 
    let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: OperationQueue.main) 
    let task = session.dataTask(with: request) {(data, response, error) in 
     var myJson: AnyObject 
     do{ 
      myJson = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject 
      if myJson.count == 0{ 
       result = true 
       semaphore.signal() 
      } else{ 
       result = false 
       semaphore.signal() 
      } 
     } catch{ 
      //TODO 
      print(error) 
     } 
    } 
    task.resume() 

    semaphore.wait(timeout: .distantFuture) 
    return result! 
} 
+1

请勿“等待”。不要使用SEMAPHORES。 – matt

回答

1

你的任务是异步的,你强制解包零值,所以这就是它崩溃的原因。

你必须改变你的函数的实现也可以异步,例如使用闭包:

private func isUniqueEmail(email: String, completion: ((Bool) -> (Void))?) { 
    let requestURL = URL(string: "http://localhost/firstpostget/functions/get.php") 
    var request = URLRequest(url: requestURL!) 
    request.httpMethod = "POST" 
    let postParameters = "email=" + email 
    request.httpBody = postParameters.data(using: .utf8) 
    let configuration = URLSessionConfiguration.default 
    let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: OperationQueue.main) 
    let task = session.dataTask(with: request) {(data, response, error) in 
     var myJson: AnyObject 
     do{ 
      myJson = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject 
      if myJson.count == 0 { 
       completion?(true) 
      } else{ 
       completion?(false) 
      } 
     } catch{ 
      //TODO 
      print(error) 
     } 
    } 
    task.resume() 
} 

现在你可以以这种方式使用此功能:

isUniqueEmail(email: "[email protected]") { result in 
    if result { 
     print("email unique") 
    } else { 
     print("email not unique") 
    } 
} 
+0

非常感谢!这很好。:) –

+0

对不起,实际上我需要使用布尔来验证结果,而不是只打印到控制台。我不能用你的解决方案来做到这一点。 –

+0

当然可以。你有你的BOOL里面的结果变量 –

1

我想你应该重新考虑您用来从请求中获取数据的模式,您应该考虑使用自定义的处理程序/回调方法,并将其与您尝试检查的电子邮件一起传递。请参阅下面的例子:

private func isUniqueEmail(email: String, handler: ((_ result: Bool) -> Void)?) -> Void { 
    let requestURL = URL(string: "http://localhost/firstpostget/functions/get.php") 
    var request = URLRequest(url: requestURL!) 
    request.httpMethod = "POST" 
    let postParameters = "email=" + email 
    request.httpBody = postParameters.data(using: .utf8) 
    let configuration = URLSessionConfiguration.default 
    let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: OperationQueue.main) 
    let task = session.dataTask(with: request) {(data, response, error) in 
     var myJson: AnyObject 
     var result: Bool = false 
     do{ 
      myJson = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject 

      if myJson.count == 0 { 
       result = true 
      } 

      guard handler != nil else { 
       return 
      } 

      handler!(result) 

     } catch{ 
      //TODO 
      print(error) 
     } 
    } 
    task.resume() 
} 

运行:

isUniqueEmail(email: "[email protected]", handler: { result in 
    print(result) // true || false 
}) 

如果你真的想往下走 “等待”,然后路线采取了在的

https://developer.apple.com/documentation/dispatch/dispatchgroup

DispatchGroup
0

你可以使用URlSession,如:

 func isUniqueEmail(email: String,completion: @escaping (Bool) ->()) { 

    var request = URLRequest(url: URL(string: "http://localhost/firstpostget/functions/get.php")!) 
    request.httpMethod = "POST" 
    let postString = "email=\(email)" 
    request.httpBody = postString.data(using: .utf8) 


    // loading to wait request 
    UIApplication.shared.isNetworkActivityIndicatorVisible = true 


    let task = URLSession.shared.dataTask(with: request) { data, response, error in 

     // we get request request 

     UIApplication.shared.isNetworkActivityIndicatorVisible = false 

     guard let data = data, error == nil else {             // check for fundamental networking error 
      print("error=\(String(describing: error))") 
      completion(false) 

      return 
     } 

     if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {   // check for http errors 
      print("statusCode should be 200, but is \(httpStatus.statusCode)") 
      print("response = \(String(describing: response))") 
      completion(false) 
     }else{ 

      completion(true) 

     } 


     let responseString = String(data: data, encoding: .utf8) 
     print("responseString = \(String(describing: responseString))") 
    } 



    task.resume() 
} 

并在代码中使用像

self.isUniqueEmail(email: "your Email") { (isExit) in 

    if isExit { 


    }else{ 


    } 
} 
+0

对不起,我没有真正得到你的答案。如果对请求有任何响应,并且无论我输入的是否总是执行if isExit,我都无法再看到该检查。 –

+0

你会调用这个方法,如果有响应isExit是真的,如果不是它将是假的 –

+0

它不工作。无论是否有回应,isExit总是如此。 –

0

尝试使用这样的:

ApihelperClass

static let sharedInstance = ApihelperClass() 

typealias CompletionHandler = (_ success:Bool, _ error:Bool, _ result:NSDictionary) -> Void 
typealias ErrorHandler = (_ success: Bool, _ error:Bool) -> Void 

    func callPostRequest(_ urlPath: String, params:[String: AnyObject], completionHandler: @escaping CompletionHandler, errorHandler:@escaping ErrorHandler){ 

     print("urlPath:==> \(urlPath) ") 
     let session = Foundation.URLSession.shared 
     let url = URL(string: urlPath) 
     var request = URLRequest(url : url!) 
     request.httpMethod = "POST" 

     do { 

      let jsonData = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted) 

      request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type") 
      request.httpBody = jsonData 

      session.dataTask(with: request, completionHandler: { data, response, error in 
       OperationQueue.main.addOperation { 

        guard error == nil && data != nil else {               // check for fundamental networking error 
         print("error=\(error)") 
         errorHandler(false, true) 
         return 
        } 

        if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {   // check for http errors 
         print("statusCode should be 200, but is \(httpStatus.statusCode)") 
         //       print("response = \(response)") 
        } 

        let responseString = String(data: data!, encoding: String.Encoding.utf8) 
        print("responseString = \(responseString!)") 

        if let responsedata = responseString!.data(using: String.Encoding.utf8)! as? Data{ 

         do { 

          let jsonResult:NSDictionary = try JSONSerialization.jsonObject(with: responsedata, options: []) as! NSDictionary 
          print("Get The Result \(jsonResult)") 
//parse your jsonResult as per your requirements 
          if error != nil { 
           print("error=\(error)") 

           completionHandler(false, true, jsonResult)// 
          } 


          if let str = jsonResult["success"] as? NSNull { 
           print("error=\(str)") 

           completionHandler(false, true, jsonResult) 

          } 
          else { 
           let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue) 
           //         print("Response string : \(responseString)") 
           completionHandler(true, false, jsonResult) 
          } 



         } catch let error as NSError { 
          print(error.localizedDescription) 
         } 
        } 
       } 
      }) .resume() 
     }catch { 
       print("Error ->Catch") 
     } 
    } 

添加到您的视图 - 控制

func isUniqueEmail(email: String){ 
    ApihelperClass.sharedInstance.callPostRequest("http://localhost/firstpostget/functions/get.php", params: ["email":email as AnyObject], completionHandler: { (success, error, result) in 
     //success 200 
    }) { (success, error) in 
     //error 
    } 
} 
+0

非常感谢您的答案。我会在哪里放Apihelper类? –

+0

创建Apihelper.swift并粘贴该代码 – Yuyutsu

0

好吧,我刚刚找到了解决方案。实际上我的信号量方法和调度组一样工作。该任务只需要URLSession.shared.dataTask

还是非常感谢所有的答案。