Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift "is" operator with type stored in variable

Tags:

types

swift

This piece of code works as expected. "integer is int" is printed in output.

let integer = Int()

if integer is Int {
    println("integer is int")
}
else {
    println("integer is not int")
}

I want to use is operator in the same way as I can use isKindOfClass method - with class (or rather type) stored in variable. It would look like this:

let integer = Int()
let intType : Any = Int.self

if integer is intType {
    println("Integer is int")
}
else {
    println("Integer is not int")
}

Unfortunately this produce an error: Use of undeclared type 'IntType'.

IntType in if condition has even a different color (if you paste it to playground) than in other places in source code, suggesting that (as the error message says) its being treated as a class name (like IntType would be a class). But it isn't. It means that is operator cannot be used with variables on the right side?

I want to use is operator because it can compare not only classes, but also other types.

How can I check if value has type which I expect?


I found dirty solution, but it's really far from being reliable...

let integer = Int()
let intType : Any = Int.self

func ==(left: Any, right: Any) -> Bool {
    let leftString = "\(left)"
    let rightString = "\(right)"
    return leftString == rightString
}

if (integer.dynamicType as Any) == intType {
    println("true")
}
else {
    println("false")
}

Works perfect, but be careful - cause this one is also true:

if (integer.dynamicType as Any) == ("Swift.Int" as Any) {
    println("true")
}
else {
    println("false")
}

Is there a better way?


Ok, I'll explain further what do I want to achieve. I have object which manages instances of generic class instances. At some point I need to pick one of those generic class instances basing on type of generic. Example:

class GenericClass<T> {}

struct ToolInfo {
    let tool : AnyObject
    let jobType : Any
}

class Manager {
    var tools = Array<ToolInfo>()

    func pickToolForTheJob(job : Any) -> AnyObject {
        return tools.magicMethodWhichReturnProperTool()
    }
}

let viewTool = GenericClass<UIView>()
let rectangleTool = GenericClass<CGRect>()

let manager = Manager()
manager.tools.append(ToolInfo(tool: viewTool, jobType: UIView.self))
manager.tools.append(ToolInfo(tool: rectangleTool, jobType: CGRect.self))

manager.pickToolForTheJob(UIView()) // i want to get viewTool here
manager.pickToolForTheJob(CGRect()) // i want to get rectangleTool here

Currently i have ToolInfo struct, because as far as I know its not possible to get type passed in <> while instantiating generic class object. But I'm still unable to compare it.

like image 411
karolszafranski Avatar asked Aug 06 '15 14:08

karolszafranski


People also ask

How to check the type of an object in Swift?

“Use the type check operator (is) to check whether an instance is of a certain subclass type.

Is operator in Swift?

Swift supports the four standard arithmetic operators for all number types: Addition ( + ) Subtraction ( - ) Multiplication ( * )

What is downcasting in Swift?

Swift Language Type Casting Downcasting operator attempts to cast to a subtype. It can fail, therefore it returns an optional.

What is use of as in Swift?

Operator. Prior to Swift 1.2, the as operator could be used to carry out two different kinds of conversion, depending on the type of expression being converted and the type it was being converted to: Guaranteed conversion of a value of one type to another, whose success can be verified by the Swift compiler.


1 Answers

It means that is operator cannot be used with variables on the right side?

Correct. The right side of is must be hard-coded at compile-time.

If you don't need polymorphism and your types are class types, you can use === to compare the dynamicType of an instance with a class type. That's the only way you're going to get a type-in-a-variable on the right side of something in pure Swift.

like image 172
matt Avatar answered Sep 30 '22 23:09

matt