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?
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.
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.
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.
@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.
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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With