mergesort mergesort - 4 months ago 9
iOS Question

How can I chain functions and choose which one to execute in Swift?

I want to be able to chain functions as seen below and choose between them. In this contrived example, I hardcoded "function_b", but in the ideal world, I'd like it to be random or even controlled by a server. I know that I can create the same effect in different ways, but I like the way this code reads, so I want to do it like this.

ExecutionManager("function_b").add("function_a") {
//some code
}.add("function_b") {
//more code
}.add("function_c") {
//other code
}

Answer

Your snipped of code does not make much sense to me. E.g. what should mean this part?

ExecutionManager("function_b")

You are just passing a string to the initializer of ExecutionManager. What should be the meaning of that?

Let's try

However if you want to be able to add a list of functions with this type

() -> ()

and then execute them (all of them or just some of them) you could define your ExecutionManager like this

class ExecutionManager {

    typealias FunctionType = () -> ()

    private var functions = [(String, FunctionType)]()

    func add(funcName: String, function: FunctionType) -> ExecutionManager {
        functions.append(funcName, function)
        return self
    }

    func runAll() {
        functions.forEach { $0.1() }
    }
}

Now you can

ExecutionManager().add("sayHello") { 
    print("hello")
}.add("sum 1 + 1") {
    let sum = 1 + 1
    print(sum)
}.add("say goodbye") { 
    print("goodbye")
}.runAll()

The result is

hello
2
goodbye

Random

To run a only a function based on some logic look at this code. here I am generating a random index and the executing only one function

Extension

extension ExecutionManager {
    func runRand() {
        guard functions.isEmpty == false else { return }
        let rand = Int(arc4random_uniform(UInt32(functions.count)))
        functions[rand].1()
    }
}

Example

ExecutionManager().add("sayHello") {
    print("hello")
}.add("sum 1 + 1") {
    let sum = 1 + 1
    print(sum)
}.add("say goodbye") {
    print("goodbye")
}.runRand()

Output

2

Update

With this version we remove the invocation of runRand at the end

@HyperZ Thanks for the hint.

import Foundation

class ExecutionManager {

    typealias FunctionType = () -> ()

    private var functions = [(String, FunctionType)]()

    func add(funcName: String, last:Bool=false, function: FunctionType) -> ExecutionManager {
        functions.append(funcName, function)
        if last {
            runRand()
        }
        return self
    }

    func runRand() {
        guard functions.isEmpty == false else { return }
        let rand = Int(arc4random_uniform(UInt32(functions.count)))
        functions[rand].1()
    }
}

Code

ExecutionManager().add("sayHello") {
    print("hello")
}.add("sum 1 + 1") {
    let sum = 1 + 1
    print(sum)
}.add("say goodbye", last:true) {
    print("goodbye")
}

Output

hello
Comments