Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift, cast to type by a given string if let .. as ? someString

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!

like image 965
Daniel Krom Avatar asked Aug 02 '15 08:08

Daniel Krom


People also ask

How do I cast type in Swift?

Type casting in Swift is implemented with the is and as operators. These two operators provide a simple and expressive way to check the type of a value or cast a value to a different type. You can also use type casting to check whether a type conforms to a protocol, as described in Checking for Protocol Conformance.

What is if let Swift?

The “if let” allows us to unwrap optional values safely only when there is a value, and if not, the code block will not run. Simply put, its focus is on the “true” condition when a value exists.

Is vs AS in Swift?

Type casting in Swift is implemented with the is and as operators. is is used to check the type of a value whereas as is used to cast a value to a different type.

What is the difference between Upcast and downcast in Swift?

Downcasting is the opposite of upcasting, and it refers to casting an object of a parent class type to an object of its children class. Downcasting is used to reconvert objects of a children class that were upcasted earlier to generalize. Let's say you own two cars and three trucks.


2 Answers

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!"
} 
like image 65
vacawama Avatar answered Oct 13 '22 16:10

vacawama


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
  }
}
like image 42
vadian Avatar answered Oct 13 '22 16:10

vadian