I'd like to have an array appended with values from database in viewDidLoad() so that I can extract a value and assign it to an UILabel.text after loading the view.
The codes:
var tagArr = [Tag]()
override func viewDidLoad() {
super.viewDidLoad()
let AA = fetchTagPool()
print(AA)
}
func fetchTagPool() -> [Tag]{
API.Tag.observeTagPool {(tag) in
self.tagArr.append(tag)
print(self.tagArr)
}
return self.tagArr
}
The result of print(AA)
is an empty array as []
while that of print(self.tagArr)
is the expected array appended with value from database.
How do I fix the code to make print(AA)
work as print(self.tagArr)
does?
Many thanks
The call to API.Tag.observeTagPool
is asynchronous and it will finish after fetchTagPool()
has returned the empty self.tagArr
.
You need to change fetchTagPool
to return the value through a callback
function like this:
override func viewDidLoad() {
super.viewDidLoad()
// Note: This will print AA after viewDidLoad finishes
// Use trailing closure syntax to pass the trailing closure
// as "callback". Then fetchTagPool calls "callback", this
// closure will receive the value as AA and print it and
// update the UILabel
fetchTagPool() { AA in
print(AA)
// Use value to update a label
myLabel.text = AA[0].name
}
print("This will print first")
}
func fetchTagPool(callback: ([Tag]) -> Void) {
API.Tag.observeTagPool { tag in
self.tagArr.append(tag)
print(self.tagArr)
callback(self.tagArr)
}
}
If your API.Tag.observeTagPool
runs on a background queue and doesn't return to the main queue to return its value, you should move to the main queue before updating the value in your property like this:
func fetchTagPool(callback: ([Tag]) -> Void) {
API.Tag.observeTagPool { tag in
DispatchQueue.main.async {
self.tagArr.append(tag)
print(self.tagArr)
callback(self.tagArr)
}
}
}