4

I have made a query in parse and fetched an array of GeoPoint coordinates. This was done inside a closure. I can only access the array values inside that closure. I need to be able to use those value so they can be used as annotations on a map but I can't get to them. Can somebody tell me how to get the array values out of the closure.

code:

var user = PFUser.currentUser()
user["location"] = geopoint

var query = PFUser.query()
query.whereKey("location", nearGeoPoint:geopoint)
query.limit = 10
query.findObjectsInBackgroundWithBlock({ (objects: [AnyObject]!, error: NSError!) -> Void in

    for object in objects {

        var user:PFUser = object as PFUser
        var otherUsersCoord = [PFGeoPoint]()
        otherUsersCoord.append(user["location"] as PFGeoPoint)

        println("The other users coords are: \(otherUsersCoord)")
    }

})}
jscs
  • 63,694
  • 13
  • 151
  • 195

2 Answers2

4

Declare otherUsersCoord as a var outside the closure expression, rather than inside it. When it is assigned to within the closure, that change will be reflected in the variable outside the closure. This is known as “capturing” otherUsersCoord. Capturing external context is what makes closures more than just functions.

Beware though, you still need to wait for the closure to actually run before the variable will have the value you decide. It won’t be instantly synchronously available. Also, capturing external variables keeps them alive and can occasionally result in cyclic references and similar problems (this is why sometimes when you refer to a member variable or function you get a warning about “capturing self”).

Airspeed Velocity
  • 40,491
  • 8
  • 113
  • 118
  • I have tried that and it is coming back as nothing is in the array, hence why the `otherUsersCoord` is inside the closure. Like you said it is something to do with the fetching hasn't finished. is there a way so this can be done? –  Jan 04 '15 at 15:58
  • add the annotations only after the closure is called. call the add annotations method inside the closure after assigning the property. – rakeshbs Jan 04 '15 at 16:30
  • That’s a bit of a different question. This answer gives into on how to wait for the closure to complete: http://stackoverflow.com/a/18021919/3925941 (it’s in Obj-C but not hard to translate). – Airspeed Velocity Jan 04 '15 at 16:54
  • Ok thank you for clearing this up, I have run the annotations inside the block. I just would of preferred to run it outside the block. –  Jan 04 '15 at 17:27
  • This doesn't yield results anymore. – Dark Innocence Dec 22 '16 at 11:35
0

You would usually do something like:

If the closure is in a method on some helper class, pass it a completion block parameter that takes the array as a parameter. When the completion block is called, store the array as an instance variable (and trigger an update to your UI) or create the annotations and set them onto your map view (which would be an instance variable).

If the closure is in a method on your class that owns the map view then you can skip the completion block part and just deal with the array directly to update your instance variable / map.

Wain
  • 118,658
  • 15
  • 128
  • 151