10

I'm trying to store a dictionary var items : [String:(type:String,item:AnyObject)] = [:]

for example the key is "foo" and items["foo"]?.type = "UILabel"

I want to convert to AnyObject by a given type from a string.

is it possible to do something like this?:

                                                 //This is a string
if let myConvertedItem = items["file"]!.item as? items["file"]!.type{
     //myConvertedItem is UILabel here..
}

is there's a better way to do this?

edit: I saw this function _stdlib_getTypeName() but swift doesn't recognize it. how can I make it declared? will it work also on AnyObject?

The Solution I'm not looking for:

do something like this:

if items["file"]!.item is UILabel{
     //ok it's UILabel
}

if items["file"]!.item is SomeOtherClassName{
    //ok it's some other class name
}

because this if list might be very long

thanks!

vacawama
  • 150,663
  • 30
  • 266
  • 294
Daniel Krom
  • 9,751
  • 3
  • 43
  • 44
  • Are you looking for a dynamic solution like: http://stackoverflow.com/questions/24030814/swift-language-nsclassfromstring ? – Stefan Aug 02 '15 at 09:02
  • Did you try to save in the dictionary an `AnyClass` object instead a simple string? – LuckyStarr Aug 02 '15 at 09:04

2 Answers2

6

is it possible to do something like this?:

                                             //This is a string
if let myConvertedItem = items["file"]!.item as? items["file"]!.type{
     //myConvertedItem is UILabel here..
}

No. That is not possible. Swift knows at compile time the types of all of its variables. You can option-click on a variable and Swift will tell you what it is. You cannot have a variable assuming a type at run time.

Look at this little example:

let random = arc4random_uniform(2)
let myItem = (random == 0) ? 3 : "hello"

You'd like myItem to be an Int if random == 0 and a String if random == 1, but the Swift compiler makes myItem to be NSObject because it treats the 3 as an NSNumber and "hello" as an NSString so that it can determine the type of myItem.


Even if that worked, what would you do with it? At the point of //myConvertedItem is UILabel here.. Swift would know that myConvertedItem is a UILabel, but the code you write wouldn't know. You'd have to do something to know that it was a UILabel before you could do UILabel things to it.

if items["file"]!.type == "UILabel" {
    // ah, now I know myConvertedItem is a UILabel
    myConvertedItem.text = "hello, world!"
}

It would be the same amount of code as the way you don't want to do it:

if myItem = items["file"]?.item as? UILabel {
    // I know myItem is a UILabel
    myItem.text = "hello, world!"
} 
vacawama
  • 150,663
  • 30
  • 266
  • 294
4

Is a switch expression a suitable solution for you?

if let item: AnyObject = items["file"]?.item {
  switch item {
  case let label as UILabel:
    // do something with UILabel
  case let someOtherClass as SomeOtherClassName:
   // do something with SomeOtherClass

  default:
    break
  }
}
vadian
  • 274,689
  • 30
  • 353
  • 361
  • it is a nice solution to go over switch case let as.. didn't know it is possible in switch. +1 for that, but it's still the same problem, this list might be long, I want to do it generic that I can hold X types of classes – Daniel Krom Aug 02 '15 at 08:53
  • 1
    I suspect this is not possible. To send messages to an object in Swift you have to cast `AnyObject` to a specific type – vadian Aug 02 '15 at 09:02