swift BUTCHER swift BUTCHER - 6 months ago 23
Swift Question

When to use closures in swift?

I am been to ios development for few months and eager to implement new things in my programming pattern.

Now i am learning closures and knew little things about its syntax,knew it can be used instead of delegate for callbacks. As well as implemented it in some UIViewAnimation and for sorting.

But really i want to know its uses apart from that.i.e where should we use closures in our basic programming. Like we use delegate when we want to send information from child to parent.. So any explanation or brief example on its actual which can be used in our day to day swift programming would be helpful?

Can anyone tell me how these closure actually computes the value

reversed = sorted(names, { (s1: String, s2: String) -> Bool in return s1 > s2 } )


In these example there is names and closure as an argument to a method..but how does this actually computes ?

Can you please explain how these works when passing closures in this animation code :

UIView.animateWithDuration(duration: NSTimeInterval,
animations: (() -> Void)?,
completion: ((Bool) -> Void)?)


I really want to know about the flow?

Answer

The two most used cases are completion blocks and higher order functions in Swift.

Completion blocks: for example, when you have some time consuming task, you want to be notified when that task is finished. You can use closures for that, instead of a delegate (or many other things)

func longAction(completion: () -> ()) {
    for index in veryLargeArray {
        // do something with veryLargeArray, which is extremely time-consuming 
    }
    completion() // notify the caller that the longAction is finished 
}

//Or asynch version
func longAction(completion: () -> ()) {

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {

        for elem in veryLargeArray {
            // do something with veryLargeArray, which is extremely time-consuming
        }
        dispatch_async(dispatch_get_main_queue(), { 
            completion() // notify the caller that the longAction is finished 
        })
    }
}

longAction { print("work done") }

In the example above, when you have a time consuming task, you want to know when the for loop finishes iterating through the very large array. You put the closure { println("work done") } as an input parameter for the function which will be executed after the for loop finishes its work, and print "work done". And what happened is that you gave a function (closure) to longAction and name it to completion, and that function will be executed when you call completion in longAction.

Higher order functions: you can use closures as input parameters for higher order functions, for example:

let array = [1, 2, 3]
let smallerThanTwo = array.filter { $0 < 2 }

With this, you can filter out the numbers that are smaller than 2.

UPDATED About how sorted (probably) works:

So the idea is, that sorted will go through the array, and compare two consecutive elements (i, i + 1) with each other, and swap them, if needed. What does it mean "if needed"? You provided the closure { (s1: String, s2: String) -> Bool in return s1 > s2 }, which will return true if s1 is lexiographically greater than s2. And if that closure returned true, the sorted algorithm will swap those two elements, and countinues this with the next two elements (i + 1, i + 2, if the end of the array is not reached). So basically you have to provide a closure for sorted which will tell "when" to swap to elements.