Call a method with dynamic class name in swift

  • A+
Category:Languages

How can we call class functions with a dynamic class name?

Assume the following example where I have two class with methods with same signature

class Foo{    class func doSomething()  }  class Foobar {    class func doSomething() }  class ActualWork{    //call following method with a variable type so that it accepts dynamic class  name    func callDynamicClassMethod(x: dynamicClass)     x.doSomething()    } 

How can this be implemented so that x accepts values at run time

Edit: Sorry, I missed to mention that I was looking for any other ways other than protocol oriented approach. This is more of an exploratory question to explore if there is a more direct approach/pods/libraries to achieve this.

 


I liked this question, because it made me to think a lit'bit outside of the box.

I'll answer it, by dividing it into a few parts.

First

call class functions

Class function is basically a Type methods, which can be achieved using the static word inside the class context.

Taking that into account, you can get a simple solution, using protocol and passing the class reference (conforming to that protocol) like this:

protocol Aaa{    static func doSomething(); } class Foo : Aaa{   static func doSomething() {     print("Foo doing something");   } } class FooBar : Aaa{   static func doSomething() {     print("FooBar doing something");   } }  class ActualWork{    //Using class (static) method   func callDynamicClassMethod <T: Aaa> (x: T.Type) {     x.doSomething();   } }   //This is how you can use it func usage(){     let aw = ActualWork();      aw.callDynamicClassMethod(x: Foo.self);     aw.callDynamicClassMethod(x: Foo.self); } 

Second

In case you don't really need the method on the class context, you may consider using instance methods. In that case the solution would be even simpler, like this:

protocol Bbb{   func doSomething(); } class Bar : Bbb{   func doSomething() {     print("Bar instance doing something");   } } class BarBar : Bbb{   func doSomething() {     print("BarBar instance doing something");   } } class ActualWork{   //Using instance (non-static) method   func callDynamicInstanceMethod <T: Bbb> (x: T){     x.doSomething();   } } //This is how you can use it func usage(){    let aw = ActualWork();     aw.callDynamicInstanceMethod(x: Bar());     aw.callDynamicInstanceMethod(x: BarBar()); } 

Third

If you need to use the class func syntax, as OP originally did:

class func doSomething()

You CANNOT simply use a protocol. Because protocol is not a class... So compiler won't allow it.

Call a method with dynamic class name in swift

But it's still possible, you can achieve that by using Selector with NSObject.perform method

like this:

class ActualWork : NSObject{      func callDynamicClassMethod<T: NSObject>(x: T.Type, methodName: String){         x.perform(Selector(methodName));     }  }  class Ccc : NSObject{     @objc class func doSomething(){         print("Ccc class Doing something ");     }  }  class Ddd : NSObject{     @objc class func doSomething(){         print("Ccc class Doing something ");     }      @objc class func doOther(){         print("Ccc class Doing something ");     } }  //This is how you can use it func usage() {     let aw = ActualWork();      aw.callDynamicClassMethod(x: Ccc.self, methodName: "doSomething");     aw.callDynamicClassMethod(x: Ddd.self, methodName: "doSomething");     aw.callDynamicClassMethod(x: Ddd.self, methodName: "doOther");  } 

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: