Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift: Enums that use closures?

I’m creating an application where an unlimited amount of rules could be applied to an unlimited amount of nodes.

I'm planning on using core data as the datastore and creating a simple one to many relationship between node and rule.

In objective-c I would probably create classes for each of the rules and have them conform to a protocol.

NSArray *ruleClassNames = @[@"SimpleRuleA",@"SimpleRuleB",@"BigFatComplicatedRule"];

int ruleType = [someNode.rules firstObject];
Class class = NSClassFromString(ruleClassNames[ruleType]);

[(ruleClassProtocol*)class performSelector:@selector(runRuleOnNode:) withObject:someNode];

What would be the most elegant way of doing this in swift?

like image 459
Chris Avatar asked Jul 16 '15 09:07

Chris


People also ask

How do you use closures in Swift?

Closure ParametersInside the closure, (name: String) specifies that the closure accepts the String type parameter named. Notice that we have used in to separate closure parameter with body. Here, we have passed a string value "Delilah" to our closure. And finally, the statement inside the closure is executed.

What are the types of closures in Swift?

As shown in the above table, there are three types of closures in Swift, namely global functions, nested functions, and closure expressions. They differ in several aspects, including their use scopes, their names, and whether they capture values, which will be discussed more in a later section.

Can Swift enums have methods?

Swift's Enum can have methods. It can have instance methods and you can use it to return expression value for the UI. Let's look at the code above.

What's an Autoclosure Swift?

@autoclosure in Swift is a type of closure that allows to omit braces and make it look like a normal expression. Under the hood, however, it's still a closure. By understanding what this means, we can improve the efficiency of our code. The @autoclosure keyword might be new to you.


1 Answers

Solution

If we want to add a closure to an enum first of all lets define the type of the closure.

typealias Logic = () -> (String)

Then the enum:

enum Rule {
    case SimpleRuleA(Logic)
    case SimpleRuleB(Logic)
    case BigFatComplicatedRule(Logic)
}

That's it! Let's see now how to use this.

Usage

Let's create a couple of Logic(s):

let logic0 : Logic = { return "Logic 0" }
let logic1 : Logic = { return "Logic 1" }

And now a function to process a Rule

func processRule(rule:Rule) -> String {
    switch rule {
    case .SimpleRuleA(let logic): return "Simple Rule A, logic: \(logic())"
    case .SimpleRuleB(let logic): return "Simple Rule B, logic: \(logic())"
    case .BigFatComplicatedRule(let logic): return "Big Fat Complicated Rule, logic: \(logic())"
    }
}

Finally let's combine every possible rule with every possible Logic...

let aWithLogic0 = Rule.SimpleRuleA(logic0)
let aWithLogic1 = Rule.SimpleRuleA(logic1)
let bWithLogic0 = Rule.SimpleRuleB(logic0)
let bWithLogic1 = Rule.SimpleRuleB(logic1)
let fatWithLogic0 = Rule.BigFatComplicatedRule(logic0)
let fatWithLogic1 = Rule.BigFatComplicatedRule(logic1)

... and let's test it

processRule(aWithLogic0) // "Simple Rule A, logic: Logic 0"
processRule(aWithLogic1) // "Simple Rule A, logic: Logic 1"
processRule(bWithLogic0) // "Simple Rule B, logic: Logic 0"
processRule(bWithLogic1) // "Simple Rule B, logic: Logic 1"
processRule(fatWithLogic0) // "Big Fat Complicated Rule, logic: Logic 0"
processRule(fatWithLogic1) // "Big Fat Complicated Rule, logic: Logic 1"

Is this solution close to what you had in mind?

like image 151
Luca Angeletti Avatar answered Sep 17 '22 13:09

Luca Angeletti