Let's say I have the following asynchronous query:
var kittens: [PFObject]!
self.tempView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "pushToView"))
var query = PFQuery(className: "Kittens")
query.findObjectsInBackgroundWithBlock({ (objects, error) in
if let kittenObjects = objects as? [PFObject] {
self.kittens = kittenObjects
}
})
I have a method that presents a view controller:
func pushToView() {
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let viewController: KittensViewController = mainStoryboard.instantiateViewControllerWithIdentifier("kittensViewController") as! KittensViewController
viewController.kittens = self.kittens
self.presentViewController(viewController, animated: true, completion: nil)
}
Because I'm setting self.kittens
inside of an asynchronous query block it obviously doesn't work when I try to access self.kittens
inside the presented view controller (it's always null).
What's the best method to get something like this working?
There are a couple of options. The main thing is that you need to update KittensViewController
when the query completes.
Make KittensViewController
a property in the view controller that holds the kittens array. When the query completes, you not only update self.kittens
, but also self.kittensViewController.kittens = kittenObjects
. This is not best design, but it should work.
Better design would be to have the query in an own controller class that fires a NSNotification when done. Then, you could listen anywhere on your code when new kittens arrive and update your views.
var query = PFQuery(className: "Kittens")
query.findObjectsInBackgroundWithBlock({ (objects, error) in
if let kittenObjects = objects as? [PFObject] {
dispatch_async(dispatch_get_main_queue()) {
NSNotificationCenter.defaultCenter().postNotificationName("KittensQueryDidFinish", object:kittenObjects, userInfo:dataDict))
}
})
In your viewDidLoad
add the following:
NSNotificationCenter.defaultCenter().addObserverForName("KittensQueryDidFinish", object: nil, queue: NSOperationQueue.mainQueue) { note in
let kittens = note.object
[weak self].kittens = kittens
}
With that method, you get updates everywhere you need. Now you have to solve the problem when the kittens already have been loaded. Therefore, I'd suggest you introduce a shared controller object (aka singleton) that does the query and stores the kittens. Then you can access kittens from everywhere.