3

I have this class

class Foo{
     public class func barFunction(){}
     public class func barFunction2(){}
     public class func barFunction3(){}
}

At the moment i have a switch function to determine which bar method to call

switch bar{
      case "bar": Foo.barFunction(param:Double)
      case "bar2": Foo.barFunction2(param:Double)
      case "bar3": Foo.barFunction3(param:Double)
      default: return
}

This whole thing would be a lot easier if i could compose the name of the bar function by concatenating strings and just call the method by string name.

I've read that in Swift, closures are the way to go, but i can't really figure out how closures would make it easier than the switch operation.

EDIT: Just to be clear, i want to call a class func with parameters by name (string)


EDIT(2): I need it to work like this because i have db objects of certain types, and either special classes or a special methods to draw those objects on the screen. When i get an object from the database i get its type as a string, which currently i'm feeding in the switch statement to determine how it will be drawn. Also, each object has different colours and i have this code right here to determine the color:

public class func getColors(iconType:String)->UIColor?{
    switch iconType{
        case "type1": return Assets.type1Color
        case "type2": return Assets.type2Color
        case "type3": return Assets.type3Color
        case "type4": return Assets.type4Color
        ...
    default: return nil
    }
}

I feel it's redundant and that it could be simplified a lot by using strings to get variables or functions. If there is any other way to do this, please tell me.

Dănuț Mihai Florian
  • 3,075
  • 3
  • 26
  • 44
  • possible duplicate of [Q&A - Call a method from a String in Swift](http://stackoverflow.com/questions/24245262/qa-call-a-method-from-a-string-in-swift) – Ferruccio May 17 '15 at 11:31
  • "This whole thing would be a lot easier if i could compose the name of the bar function by concatenating strings and just call the method by string name" But you should be asking why you are in this situation to begin with. Why _are_ you in this situation to begin with? Swift purposely discourages / prevents this sort of string-based dynamism, and you don't really need it if you think more deeply about the nature of the problem. Describe the _underlying_ task that you are _really_ trying to solve, please. – matt May 17 '15 at 14:23
  • See my update on my answer – Arbitur May 17 '15 at 14:31
  • "When i get an object from the database i get its type as a string" You see, that's your mistake. You moved into the string world, and now you are struggling to get out. Just get its type and _stay_ in the world of types. You can match things up _by type_. This is what types are _for_ (among other things). – matt May 17 '15 at 15:02
  • Believe me, I know what I'm talking about. I have an app that does exactly the same thing, and in Objective-C I was doing the same thing you are doing with strings. When I switched to Swift I had to rewrite and discovered how to use types and I'm so much happier now. It is much _less_ complicated, much _less_ hacky, and much _less_ error-prone. – matt May 17 '15 at 15:04
  • @matt Could you give us an example of what you mean? :) – Arbitur May 17 '15 at 15:07
  • @Arbitur No, I think you are handling things very well. :) – matt May 17 '15 at 15:07
  • @matt, it would be good if you could elaborate on what yo mean by "...stay in the world of types." How would you store a type to a non-object dictionary? I'm thinking of setting up an enum with a raw value. Is that what you mean? (This would be useful as a separate answer) – Duncan C May 17 '15 at 15:38
  • @DuncanC Not on _this_ question. The OP has asked how to call a function or property by string. I am saying "don't". If the OP (or you) would care to ask a _new_ question describing the situation and what he wants to do, without the "use a string" prejudice, I'm happy to help in detail. – matt May 17 '15 at 17:11
  • @matt the things you are saying are not practical with a Realm.io database. And, sadly this is what i'm using. – Dănuț Mihai Florian May 21 '15 at 06:52
  • I know only what you tell me. You concealed that in your question and tags. I don't know why it makes a difference, but I believe you. But then perhaps you should use Objective-C instead, where such dynamism is easy. – matt May 21 '15 at 08:27

1 Answers1

9

You can use NSTimer to call a selector once:

NSTimer.scheduledTimerWithTimeInterval(0, target: self, selector: Selector("barFunction"), userInfo: nil, repeats: false)

Another more elegant solution

Using closures and dictionary:

let options = [
    "bar1": { Foo.barFunction1() },
    "bar2": { Foo.barFunction2() },
    "bar3": { Foo.barFunction3() }
]

// Ways of calling the closures

options["bar2"]!()

options["bar1"]?()

let key = "bar3"
if let closure = options[key] {
    closure()
}
Community
  • 1
  • 1
Arbitur
  • 38,684
  • 22
  • 91
  • 128