What a quick way to send the same function call to multiple objects

In objective-c, we have -forwardInvocation: this can be used as follows:

-(void)forwardInvocation:(NSInvocation*) anInvocation{ BOOL didForward = NO; //iterate over our proxied objects for(id proxyObject in self.proxyObjects){ //invoke the with the proxy object if it can handle the selector if ([proxyObject respondsToSelector:[anInvocation selector]]){ didForward = YES; [anInvocation invokeWithTarget: proxyObject]; } } //if we did not forward the invocation, then call super if(!didForward){ [super forwardInvocation: anInvocation]; } } 

This is useful if you have a group of specific classes for which everyone needs the same messages. For example, if you use several analytics platforms, each of which needs the same messages, but will process them in different ways.

Lets do it quickly, given what we know about the language. It starts off simply:

 func doSomething1(){ for proxyObject in proxyObjects{ proxyObject.doSomething1() } } 

But then it repeats:

 func doSomething2(){ for proxyObject in proxyObjects{ proxyObject.doSomething2() } } func doSomething3(){ for proxyObject in proxyObjects{ proxyObject.doSomething3() } } func doSomething4(){ for proxyObject in proxyObjects{ proxyObject.doSomething4() } } ....And on and on 

I know that I can use NSObject in swift, but it's just confusion in objective-c where we need it. What is a more efficient and less surefire way to deal with this in a clean fast?

+4
source share
1 answer

Swift was built to stay away from this very design. There are no dynamic posts like ObjC. Each method must be known at compile time. There is no true replacement in pure Swift. However, we can emulate (to a limited extent) that the ObjC runtime is working using the Swift closure:

 typealias MyAction = () -> Void enum ValidActions { case Hello case Goodbye } protocol MyProxyProtocol { var actions : Dictionary<ValidActions, MyAction> { get } } private class Concrete1 : MyProxyProtocol { var actions = Dictionary<ValidActions, MyAction>() init() { self.actions[.Hello] = helloWorld self.actions[.Goodbye] = goodbyeWorld } func helloWorld() -> Void { print("Hello world from concrete 1") } func goodbyeWorld() -> Void { print("Goodbye world from concrete 1") } } private class Concrete2 : MyProxyProtocol { var actions = Dictionary<ValidActions, MyAction>() init() { self.actions[.Hello] = hello } func hello() -> Void { print("Hi from concrete 2") } } public class AbstractClass { var proxyObjects = [MyProxyProtocol]() init() { self.proxyObjects.append(Concrete1()) self.proxyObjects.append(Concrete2()) } func performAction(action : ValidActions) { for proxy in self.proxyObjects { if let f = proxy.actions[action] { f() } } } } let x = AbstractClass() x.performAction(.Hello) // Both concrete classes will do this x.performAction(.Goodbye) // Only the first one will do this 

Each particular class provides actions that it can handle using the actions dictionary. Functions that handle them as stored as closures inside.

+2
source

All Articles