简体   繁体   English

在Alamofire关闭回归Bool

[英]Return Bool in Alamofire closure

I use Swift 2 and Xcode 7.1. 我使用Swift 2和Xcode 7.1。

I have a function who connect my users, but it will connect at my database with HTTP. 我有一个连接我的用户的功能,但它将使用HTTP连接我的数据库。 I use Alamofire for execute this request. 我使用Alamofire执行此请求。 I want to know, from a view controller if the user is connected. 我想知道,如果用户已连接,则从视图控制器。

I have my function connect in a class. 我的功能连接在一个类中。 And i test connection in a ViewController. 我在ViewController中测试连接。 Like this : 像这样 :

    class user {

    // ...

    func connectUser(username: String, password: String){

        let urlHost = "http://localhost:8888/project350705/web/app_dev.php/API/connect/"
        let parametersSymfonyG = [
            username, password
        ]
        let url = UrlConstruct(urlHost: urlHost).setSymfonyParam(parametersSymfonyG).getUrl()

        //var userArray = [String:AnyObject]()

        Alamofire.request(.GET, url)
            .responseString { response in

                if let JSON = response.result.value {

                    var result = self.convertStringToDictionary(JSON)!

                    if result["status"] as! String == "success"{
                        let userArray = result["user"] as! [String:AnyObject]
                        userConnect = self.saveUser(userArray)
                    } else{
                        print("ERROR-CONNECTION :\n Status :\(result["status"]!)\n Code :\(result["code"]!)")
                    }
                    return ""
                }
        }
    }

    // ...
}

class MyViewController: UIViewController {

    // ...

    @IBAction func connect(sender: AnyObject?) {

        // CONNECTION
        User.connectUser(self.username.text!, password: self.password.text!)

        // CHECK
        if userConnect != nil {
            print("connected")
        }else{
            print("NotConnected")
        }
    }

    // ...

}

First solution : Return 第一个解决方案:返回

To do so would require that my function returns a Boolean. 要这样做,我的函数将返回一个布尔值。 Only I can not use return. 只有我不能使用退货。

Alamofire.request(.GET, url)
        .responseString { response in

            if let JSON = response.result.value {

                var result = self.convertStringToDictionary(JSON)!

                if result["status"] as! String == "success"{
                    let userArray = result["user"] as! [String:AnyObject]
                    userConnect = self.saveUser(userArray)
                } else{
                    print("ERROR-CONNECTION :\n Status :\(result["status"]!)\n Code :\(result["code"]!)")
                }
                return "" // Unexpected non-void return value in void function
            }
    }

Second solution : 二解决方案:

I can also test if the user has been logged, but before testing, I must wait for the function have finished loading. 我还可以测试用户是否已经登录,但在测试之前,我必须等待功能已经完成加载。

users.connectUser(self.username.text!, password: self.password.text!)

// after 
if userConnect != nil {
    print("connected")
}else{
    print("NotConnected")
}

I would prefer return a boolean. 我宁愿返回一个布尔值。 It will facilitate the processing. 它将促进处理。 Do you have a solution ? 你有解决方案吗 ?

I would suggest employing a completion handler in your connectUser method: 我建议在你的connectUser方法中使用一个完成处理程序:

func connectUser(username: String, password: String, completion:(Bool) -> ()) {
    // build the URL

    // now perform request

    Alamofire.request(.GET, url)
        .responseString { response in
            if let JSON = response.result.value, let result = self.convertStringToDictionary(JSON) {
                completion(result["status"] as? String == "success")
            } else {
                completion(false)
            }
    }
}

You can then call it using: 然后你可以用它来调用它:

users.connectUser(username.text!, password: password.text!) { success in
    if success {
        print("successful")
    } else {
        print("not successful")
    }
}
// But don't user `success` here yet, because the above runs asynchronously

BTW, if your server is really generating JSON, you might use responseJSON rather than responseString , further streamlining the code and eliminating the need for convertStringToDictionary : 顺便说一句,如果你的服务器真的在生成JSON,你可以使用responseJSON而不是responseString ,进一步简化代码并消除对convertStringToDictionary的需求:

func connectUser(username: String, password: String, completion:(Bool) -> ()) {
    // build the URL

    // now perform request

    Alamofire.request(.GET, url)
        .responseJSON { response in
            if let JSON = response.result.value {
                completion(JSON["status"] as? String == "success")
            } else {
                completion(false)
            }
    }
}

If you've written your own server code to authenticate the user, just make sure you set the right header (because responseJSON not only does the JSON parsing for you, but as part of its validation process, it makes sure that the header specifies JSON body; it's good practice to set the header, regardless). 如果您编写了自己的服务器代码来验证用户身份,请确保设置正确的标头(因为responseJSON不仅为您执行JSON解析,而且作为其验证过程的一部分,它确保标头指定JSON body;无论如何设置标题是一种好习惯。 For example in PHP, before you echo the JSON, set the header like so: 例如在PHP中,在echo显JSON之前,设置标题如下:

header("Content-Type: application/json");

The completion handler of your Alamofire.request method is asynchronous and it doesn't have a return type specified in its signature. Alamofire.request方法的完成处理程序是异步的,并且它的签名中没有指定返回类型。 Thats why you see an error when you provide a return statement in your completion handler closure. 这就是为什么在完成处理程序闭包中提供return语句时看到错误的原因。

You will have to split your request and response processing to separate methods and call the response processing method instead of using return statement. 您必须将请求和响应处理拆分为单独的方法,并调用响应处理方法而不是使用return语句。

Alamofire.request(.GET, url).responseString { response in

        if let JSON = response.result.value {
            var result = self.convertStringToDictionary(JSON)!

            if result["status"] as! String == "success"{
                let userArray = result["user"] as! [String:AnyObject]
                userConnect = self.saveUser(userArray)
                processSuccessResponse() //Pass any parameter if needed
            } else{
                print("ERROR-CONNECTION :\n Status :\(result["status"]!)\n Code :\(result["code"]!)")
                processFailureResponse() //Pass any parameter if needed
            }
       }
}

func processSuccessResponse() {
    //Process code for success
}

func processFailureResponse() {
    //Process code for failure
}

My preferred way of doing this is to call a function in the completion handler. 我这样做的首选方法是在完成处理程序中调用一个函数。 You can also set a boolean flag in order to check if the user is connected at any given time. 您还可以设置布尔标志,以检查用户是否在任何给定时间连接。

func connectUser(username: String, password: String, ref: MyClass) {
    Alamofire.request(.GET, url)
        .responseString { response in

            var userIsConnected = false

            if let JSON = response.result.value {

                var result = self.convertStringToDictionary(JSON)!

                if result["status"] as! String == "success"{
                    let userArray = result["user"] as! [String:AnyObject]
                    userConnect = self.saveUser(userArray)
                    userIsConnected = true
                } else {
                    print("ERROR-CONNECTION :\n Status :\(result["status"]!)\n Code :\(result["code"]!)")
                }

            } else {
                print("Response result nil")
            }

            ref.finishedConnecting(userIsConnected)
        }
    }
}

class MyClass {
    var userIsConnected = false

    func startConnecting() {
        connectUser(username, password: password, ref: self)
    }

    func finishedConnecting(success: Bool) {
        userIsConnected = success

        ... post-connection code here
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM