Issue
I'm currently writing a function in Swift
to remove all annotations from the map.
I want to add a fade out effect when they are being removed, so I thought about the following argument:
Iterate over all annotations
for each annotation change its alpha to 0 with animations
when everything has completed - remove annotations from the map.
The code that I have so far changes already the alpha of each marker, but I don't know how to invoke the function responsible for removing markers when everything else is completed.
I have two functions:
func removeMarkersFromMap(){
self.array.removeAll()
let annotationsToRemove = mapView.annotations.filter { $0 !== mapView.userLocation }
for annotation in annotationsToRemove {
let pinView = mapView.view(for: annotation)
UIView.animate(withDuration: 2, delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: {
pinView?.alpha = 0.0
}, completion: { (finished: Bool) -> Void in
print("removed single pin")
})
}
}
and:
func removeCompletelyAnnotations(){
let annotationsToRemove = mapView.annotations.filter { $0 !== mapView.userLocation }
self.mapView.removeAnnotations( annotationsToRemove )
}
How can I call the 2nd function when the loop inside the 1st function is completed?
Solution
The trick I use for this kind of thing is to place the final completion code in the deInit method of an object instance that is captured by the in the individual completions.
For example :
class FinalCompletion
{
var codeBlock:()->()
init(_ code:@escaping ()->()) { codeBlock = code }
func waitForLast() {}
deinit { codeBlock() }
}
So in your calling code you can proceed as follows :
func removeMarkersFromMap()
{
...
// setup the final completion in a local variable
let removeAnnotation = FinalCompletion(removeCompletelyAnnotations)
for annotation in annotationsToRemove
{
let pinView = mapView.view(for: annotation)
UIView.animate(withDuration: 2, delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: {
pinView?.alpha = 0.0
}, completion: { (finished: Bool) -> Void in
print("removed single pin")
// reference the local variable to make it part of the capture
removeAnnotation.waitForLast()
})
}
}
The way it works is that the local variable (FinalCompletion object) will remain "alive" as long as at least one of the completion blocks is also alive. When the completion blocks are executed, they go out of scope and release their hold on the captured local variable. When the last completion block is executed and goes out of scope, the local variable no longer has any references to it so it also goes out of scope. This is when its deinit method is called. ( i.e. after all completion blocks have been executed).
Answered By - Alain T.
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.