无法从同一类中的闭包中更改变量 [swift 3.0]
Posted
技术标签:
【中文标题】无法从同一类中的闭包中更改变量 [swift 3.0]【英文标题】:Cannot change variable from a closure in the same class [swift 3.0] 【发布时间】:2016-09-27 14:59:02 【问题描述】:var serviceTypeName = [String]()
override func viewDidLoad()
super.viewDidLoad()
getServiceType()
debugPrint(serviceTypeName)
我尝试从 Web API 获取名称数组,并将其存储到数组 serviceTypeName
中。下面是我获取服务名的函数(我用的是Alamofire lib)
func getServiceType()
Alamofire.request(...
.responseJSON response in
switch response.result
case .success:
if let responseValue = response.result.value
var serviceName: [String] = []
let json = JSON(responseValue)
for (key, subJson):(String, JSON) in json["results"]
if let name = subJson["name"].string
serviceName.insert(name, at: Int(key)!)
self.serviceTypeName = serviceName
...
然而,我在这个函数之后得到了空数组[]
,就像这个函数没有做任何事情一样。我确保从服务器获得正确的数据,并在每个循环中正确输入serviceName
。但我无法将其设置为serviceTypeName
。请指出错误?
【问题讨论】:
【参考方案1】:在这个函数之后我得到了空数组
[]
,就像这个函数没有做任何事情一样。
没错,该函数没有做任何事情。更准确地说,该函数还没有做任何事情。函数后检查值过早,因为回调是异步执行的,数据到达时。
你需要把你的代码分成两部分:
第一部分启动调用,并给它一个回调,将属性设置为从调用接收到的结果 第二部分处理结果,显示属性或执行您计划执行的任何其他操作一旦回调完成设置属性,它需要启动第二部分的调用,它利用这些属性。
func getServiceType() // Part 1
...
self.serviceTypeName = serviceName
dispatch_async(dispatch_get_main_queue())
processServiceName()
func processServiceName() // Part 2
... // Do things with self.serviceTypeName
【讨论】:
DispatchQueue.main.async ...
我用这个代替dispatch_async...
会导致错误
@user2174595 我明白了,您使用的是 Swift-3,对吧?你的processServiceName()
函数是做什么的,你会得到什么样的错误?
是的。这可能只是 swift 3.0 中的语法差异。我在 func 中重新加载 UITableView。
@user2174595 它会崩溃,还是不会重新加载数据?对this question 的回答表明您的代码应该可以工作。
谢谢!有用。 @Edgar 的答案也很棒,在 Alamofire 中使用 completionHandler
【参考方案2】:
Alamofire 请求是异步的。这意味着您在 getServiceType()
中的代码将与您在 viewDidLoad()
函数中的其余代码分开运行。
在debugPrint(serviceTypeName)
被调用的时候getServiceType()
函数还没有完成处理。
解决这个问题的一种方法是在你的getServiceType()
函数中添加一个completionHandler:
func getServiceType(completionHandler: () -> ())
Alamofire.request(...
.responseJSON response in
switch response.result
case .success:
if let responseValue = response.result.value
var serviceName: [String] = []
let json = JSON(responseValue)
for (key, subJson):(String, JSON) in json["results"]
if let name = subJson["name"].string
serviceName.insert(name, at: Int(key)!)
self.serviceTypeName = serviceName
completionHandler()
...
然后你可以这样调用函数:
override func viewDidLoad()
super.viewDidLoad()
getServiceType()
debugPrint(serviceTypeName)
在这里,当异步函数触发完成处理程序时,将调用调试打印:在正确的时间。 :)
【讨论】:
这是 Xcode 告诉我添加func getServiceType(completionHandler: @escaping () -> ())
的内容。这里的escaping
是什么意思?
没问题!我没有信心向您解释什么是闭包/类型属性,所以我将把它留在这里以获取更多信息:updating-closures-to-swift-3-escaping以上是关于无法从同一类中的闭包中更改变量 [swift 3.0]的主要内容,如果未能解决你的问题,请参考以下文章
是否可以根据从 Swift 中的 UIViewController 继承的类中的另一个来初始化变量?