Krzysztof Rosiński Krzysztof Rosiński - 4 years ago 298
Swift Question

Swift - Cast Any IntegerType to Int

Is there any easy way to convert Any IntegerType to Int in Swift. I have a dictionary which contains different types of integers; UInt8, UInt16 etc. and need to convert this to Int. Is there any easier way apart of switch statement:

let x: UInt8 = 5
let any: Any = x

var size: Int
switch (any) {
case let value as Int8: size = Int(value)
case let value as UInt8: size = Int(value)
case let value as Int16: size = Int(value)
case let value as UInt16: size = Int(value)
case let value as Int32: size = Int(value)
case let value as UInt32: size = Int(value)
case let value as Int64: size = Int(value)
case let value as UInt64: size = Int(value)
case let value as Int: size = Int(value)
case let value as UInt: size = Int(value)
default: size = 0
}

Answer Source

Your problem is that you allowed Any to come into the picture. At that point, you lose a lot of power.

The other problem you're facing is that your code as written is poorly defined and Swift resists you writing code that way (basically by forcing you to be explicit). If you are passed a UInt64, there is no guarantee that size will have the same value as value. This is a very common problem when people seek an automatic way to convert between number types. Swift encourages you to think about numeric conversions because they are a common source of bugs.

There are several things you can do depending on what you're trying to solve. If you want a data structure that holds either an Int64 or a UInt64, that's easy. Just create the type you mean.

enum ParsedNumber {
    case Signed(Int64)
    case Unsigned(UInt64)
}

let numbers: [String: ParsedNumber] = [:]

Then all your values will fit in that. If you need to keep track of the width for later, that's no problem either:

struct ParsedNumber {
    enum Value {
        case Signed(Int64)
        case Unsigned(UInt64)
    }
    let width: Int
    let value: Value
}

let n = ParsedNumber(width: 32, value: .Signed(2))

This feels like the problem you're solving. If on the other hand you know your type at one point (i.e. it's Int8, not Any) and just want to be able to pass it to functions, just make the functions generic on IntegerType:

func calc<Num: IntegerType>(num: Num) { ... }

A useful tool on IntegerType is its toIntMax() method. This will trap (crash) if the value is too large, so be aware, but it's a useful way to convert arbitrary values to a known integer type. There are also SignedIntegerType and UnsignedIntegerType if you know your sign already. (You can't convert Any to these, though. You need to already have a known type somewhere.)

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download