Swift 中的闭包回调函数中的 UIAlertView

UIAlertView in closures callback function in Swift

当用户单击登录按钮时,我需要通过 api 登录。 return 结果可能失败或成功。我想用alterview来通知用户。

我在class中定义了一个全局变量:

var responseString:String = "";

在按钮点击事件中:

    @IBAction func login(sender: AnyObject) {
    sendPostLoginRequest {
      results in
        println("here:\(results)")
        self.responseString = results

    }
    var myAlert = UIAlertController(title:"Alert", message:self.responseString, preferredStyle: UIAlertControllerStyle.Alert);

    let okAction = UIAlertAction(title:"Ok", style:UIAlertActionStyle.Default, handler:nil);

    myAlert.addAction(okAction);
    self.presentViewController(myAlert, animated:true, completion:nil);

}

self.responseString 是空的,即使我可以在 sendPostLoginRequest 函数中得到它:

func sendPostLoginRequest(completionHandler:(result:String)->()){
    let name = usernamefield.text
    let password = passwordfield.text

    let request = NSMutableURLRequest(URL: NSURL(string: "http://www.xxx.xxx/api/user/login")!)
    request.HTTPMethod = "POST"
    let postString = "username=\(name)&password=\(password)"
    request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
        data, response, error in

        if error != nil {
            let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)


        }

        let json = JSON(data: data)
        println("results: \(json) ")
        self.responseString = json[0].string!
       //json[0].string! can be success or failure

        completionHandler(result:self.responseString)

    }
    task.resume()


}

我认为当您单击按钮时,显示的 alertView 没有 responseString 或 nil。问题是您预计稍后将调用该块,因此 responseString 的数据将稍后设置,但下面的代码将继续执行。

漫漫长路是:

//observe this variable and when something changes we will alert it
var responseString:String {
    didSet{
        //do some checking or other work
        presentAlert(responseString)
    }
}

@IBAction func login(sender: AnyObject) {
    sendPostLoginRequest {
        results in
        println("here:\(results)")
        self.responseString = results
    }
}

func presentAlert(msg:String){
    var myAlert = UIAlertController(title:"Alert", message:msg, preferredStyle: UIAlertControllerStyle.Alert);
    
    let okAction = UIAlertAction(title:"Ok", style:UIAlertActionStyle.Default, handler:nil);
    
    myAlert.addAction(okAction);
    self.presentViewController(myAlert, animated:true, completion:nil);
}

最简单的方法是:

 @IBAction func login(sender: AnyObject) {
    sendPostLoginRequest {
        results in
        println("here:\(results)")
        self.responseString = results
        
        dispatch_async(dispatch_get_main_queue(), { () -> Void in
            //update ui from main thread always
            self.presentAlert(results)  //may pass responseString too
        })
        
    }
}

func presentAlert(msg:String){
    var myAlert = UIAlertController(title:"Alert", message:msg, preferredStyle: UIAlertControllerStyle.Alert);
    
    let okAction = UIAlertAction(title:"Ok", style:UIAlertActionStyle.Default, handler:nil);
    
    myAlert.addAction(okAction);
    self.presentViewController(myAlert, animated:true, completion:nil);
}

如果你把代码放在闭包下面它会工作但是你会 运行 UI 来自其他线程的东西是不好的所以使用 Dispatch Async 来长期工作-运行 在单独的线程上操作。

如果有帮助请告诉我,希望有帮助。干杯!