Chris - 8 months ago 26

Swift Question

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?

Answer

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.

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?