Swift函数iOS中未返回数据[重复]
Posted
技术标签:
【中文标题】Swift函数iOS中未返回数据[重复]【英文标题】:Data not being returned in Swift function iOS [duplicate] 【发布时间】:2015-04-17 05:34:09 【问题描述】:这可能是我对 Swift 的误解。我是这门语言的新手,而且我的背景是 Perl,这让我觉得 swift 的行为与众不同。
我有 2 个文件。 ViewController.swift 和 APICalls.swift。在视图控制器中,我有一个按钮功能。在这个函数中,我正在调用 APICalls 中的另一个函数。当我这样做时,APICalls 中的 println() 正在打印正确的数据,但是,它是在按钮函数中的 println() 之后打印的。
Viewcontroller.swift
@IBAction func buttonStuff(sender: AnyObject)
var api = APICalls()
var token:String
token = api.TEST("letmein")
println("\ntokenDidLOAD = \(token)\n")
APICalls.swift
class APICalls
func TEST(command: String) -> (String)
var token:String = ""
// Form URL-Encoded Body
let bodyParameters = [
"COMMAND":command,
]
let encoding = Alamofire.ParameterEncoding.URL
// Fetch Request
Alamofire.request(.POST, "http://api.com/?v=1", parameters: bodyParameters, encoding: encoding)
.validate(statusCode: 200..<300)
.responseJSON(request, response, data, error) in
if (error == nil)
let json = JSON(data!)
token = json["TOKEN"].string!
println("jsonAPI = \(json) \n\n")
else
println("HTTP HTTP Request failed: \(error)")
return token
这是我的输出
tokenDidLOAD =
jsonAPI =
"STATUS" : "OK",
"TOKEN" : "698798765432134654",
我不明白为什么 'tokenDidLOAD' 在 jsonAPI 之前先打印。
【问题讨论】:
Difference between synchronous and asynchronous 您应该阅读 Alamofire 自述文件中的“响应处理”部分。它明确提到了异步过程。 类似问题的答案:***.com/questions/29377824/…、***.com/questions/29377824/…、***.com/questions/25141829/…(还有更多......) 【参考方案1】:因为您发出的请求是异步的。您首先返回尚不存在的令牌,然后才真正完成请求。您不需要将令牌作为TEST
函数的返回值。你的 TEST 应该是这样的:
func TEST(command: String, completion:(String)->())
var token:String = ""
// Form URL-Encoded Body
let bodyParameters = [
"COMMAND":command,
]
let encoding = Alamofire.ParameterEncoding.URL
// Fetch Request
Alamofire.request(.POST, "http://api.com/?v=1", parameters: bodyParameters, encoding: encoding)
.validate(statusCode: 200..<300)
.responseJSON(request, response, data, error) in
if (error == nil)
let json = JSON(data!)
token = json["TOKEN"].string!
println("jsonAPI = \(json) \n\n")
completion(token)
else
println("HTTP HTTP Request failed: \(error)")
那你叫它:
api.TEST("letmein", (newToken : String) in
token = newToken
println("\ntokenDidLOAD = \(token)\n")
)
【讨论】:
【参考方案2】:因为这个println("jsonAPI = \(json) \n\n")
在块语句中,一旦请求完成就会运行,在此之前编译器将运行下一个作业意味着你的println("\ntokenDidLOAD = \(token)\n")
。块将在另一个子线程上运行。
如果您想在请求完成时打印println("\ntokenDidLOAD = \(token)\n")
,请使用基于oncomplete
的块。
希望这可以帮助您解决问题。
【讨论】:
【参考方案3】:Alamofire 默认异步获取数据,这是几乎每个网站或应用程序所期望的行为。当函数到达return token
时,请求可能还没有完成。
一个想法是向 API 调用传递一个闭包,以便在请求完成后执行:
func TEST(command: String, closure: (JSON) -> ()) -> (String)
var token:String = ""
// Form URL-Encoded Body
let bodyParameters = [
"COMMAND":command,
]
let encoding = Alamofire.ParameterEncoding.URL
// Fetch Request
Alamofire.request(.POST, "http://api.com/?v=1", parameters: bodyParameters, encoding: encoding)
.validate(statusCode: 200..<300)
.responseJSON(request, response, data, error) in
if (error == nil)
let json = JSON(data!)
token = json["TOKEN"].string!
println("jsonAPI = \(json) \n\n")
closure(json)
else
println("HTTP HTTP Request failed: \(error)")
return token
然后你可以通过以下方式调用它:
api.TEST("letmein") json in
let token = json["TOKEN"].stringValue
println("\ntokenDidLOAD = \(token)\n")
闭包接受JSON
类型的对象作为参数,你可以用它来做任何你想做的事情。
还有一件事需要注意:我假设您使用的是 SwiftyJSON 库。之前,你打电话给json["TOKEN"].string!
。这个强制解包一个可选的,通常应该避免(除非你绝对确定它有一个值)。在这种情况下,您可能想改用json["TOKEN"].stringValue
。它返回String
而不是String?
【讨论】:
以上是关于Swift函数iOS中未返回数据[重复]的主要内容,如果未能解决你的问题,请参考以下文章
在 iOS Swift 中使用 Delegated 和 Protocols 从 dataTaskWithRequest 返回数据