简体   繁体   English

使用Swift闭包捕获变量

[英]Using a Swift closure to capture a variable

I have this bit of code and it obviously errors out because when I use FOO in the return statement it's outside of the scope of the function. 我有这段代码,它显然会出错,因为当我在return语句中使用FOO时,它不在函数的范围之内。 I know (I think I know) I need to use a closure to capture the variable but I can't figure out how to do that. 我知道(我想我知道)我需要使用闭包来捕获变量,但我不知道该怎么做。 Using Alamofire & SwiftyJSON. 使用Alamofire和SwiftyJSON。 Any help would be great! 任何帮助将是巨大的! Thanks! 谢谢!

  func getPlayerID(named: String) -> String {

    Alamofire.request(.GET, "URL", headers: headers)
        .responseJSON { response in


        let json = JSON.self(response.result.value!)

        for var index = 0; index < json.count; index++ {
            if json[index]["Name"].stringValue == named {
                var FOO = json[index]["FOO"].stringValue
            } // If Statement End
        } // For Loop End
    } // Alamofire Request End

     // Return Statement for getPLayerID Function

        return FOO

} // getPlayerID Function End
} // Player Struct End

The basic idea is that getPlayerID should not return anything, but rather should just have a parameter which is a closure, and once you retrieve the value you want to "return", you call the closure using that value as a parameter. 基本思想是getPlayerID不应返回任何内容,而应仅具有一个作为闭包的参数,并且一旦检索到要“返回”的值,就可以使用该值作为参数来调用闭包。

But, I'd suggest all sorts of other refinements here: 但是,我建议在这里进行各种其他改进:

  • Build an array of the strings and return that 建立一个字符串数组并返回
  • Check to see if result is a .Failure because you have no control over what various server/network issues may arise 检查result是否为.Failure因为您无法控制可能出现的各种服务器/网络问题
  • Change the closure to detect and report errors 更改关闭以检测并报告错误

But hopefully this illustrates the basic idea: 但是希望这可以说明基本思想:

Personally, I'd (a) make the String parameter to the completionHandler optional; 就我个人而言,我将(a)使completionHandlerString参数为可选; (b) add another optional error parameter; (b)添加另一个可选的错误参数; and (c) add error handling to the getPlayerID : 和(c)将错误处理添加到getPlayerID

func getPlayerID(completionHandler: ([String]?, ErrorType?) -> Void) {
    Alamofire.request(.GET, "URL", headers: headers)
        .responseJSON { request, response, result in
            switch (result) {
            case .Success(let value):
                let json = JSON.self(value)

                // variable to hold all of the results

                var strings = [String]()   

                // populate the array of strings

                for var index = 0; index < json.count; index++ {
                    if json[index]["Name"].stringValue == named {
                        strings.append(json[index]["FOO"].stringValue)
                    }
                }

                // call the completion handler with the strings

                completionHandler(strings, nil)
            case .Failure(_, let error):
                completionHandler(nil, error)
            }
    }
}

And then, when you want to call it: 然后,当您要调用它时:

getPlayerID() { strings, error in
    // use `strings` here
}

// but not here

If you make an asynchronous request you can not return a value received in response in the same function cause it needs time for request to be sent over network to the server and back. 如果发出异步请求,则无法在同一函数中返回作为响应收到的值,因为它需要一些时间才能将请求通过网络发送到服务器并返回。 The best way to solve this out is to add callback parameter to your function instead of return value. 解决此问题的最佳方法是在函数中添加回调参数,而不是返回值。

func getPlayerID(named: String, callback:(foo:String)->()) {

    Alamofire.request(.GET, "URL", headers: headers)
        .responseJSON { response in


            let json = JSON.self(response.result.value!)

            for var index = 0; index < json.count; index++ {
                if json[index]["Name"].stringValue == named {
                    var FOO = json[index]["FOO"].stringValue
                    callback(foo: FOO)   // you fire callback here..
                } // If Statement End
            } // For Loop End
    } // Alamofire Request End

} // getPlayerID Function End

Callback is a block object that will be fired when your response will be received. 回调是一个块对象,将在收到您的响应时触发。 So if response is not coming (for example, internet connection went down) callback will never fired. 因此,如果没有响应(例如,Internet连接断开),则永远不会触发回调。 Example how to use this: 示例如何使用它:

self.getPlayerID("ototo") { (foo) -> () in
    print("foo received = \(foo)")
}

Also there is a time span between sending the request and receiving the response. 在发送请求和接收响应之间还有一段时间。 So it is a good practice to add UIActivityIndicatorView in UI of your app until response is arrived (and handle timeout if internet connection suddenly went down). 因此,在应用的用户界面中添加UIActivityIndi​​catorView直到响应到来是一个好习惯(如果互联网连接突然断开,请处理超时)。

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

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