Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if AnyObject is of generic type in Swift

Let's say that I have generic class Bus:

class Bus<T> {
    func doSomething() {}
}

and I can create instance of it:

var myBus = Bus<String>()

Now I have a function that takes one parameter of the AnyObject and tests it's type:

func checkType(object: AnyObject) {
    if let foo = object as? String {
        println("string")
    }
}

My problem is that I can't see a way to check if object is of type Bus and run function doSomething() if it is of type Bus. Any help would be appreciated.


Edit: Protocols also don't seem to solve this the way they should.

import Foundation

@objc protocol BusProtocol {
    func doSomething() -> Void
}

class Bus<T> : BusProtocol {
    func doSomething() -> Void {
        println("asdf")
    }
}

func checkType(object: AnyObject) {
    if let foo = object as? Bus<AnyObject> {
        foo.doSomething() // no match
    }
    if let foo = object as? Bus<Any> {
        foo.doSomething() // no match
    }
    if let foo = object as? Bus<String> {
        foo.doSomething() // prints "asdf"
    }
    if let foo = object as? BusProtocol {
        foo.doSomething() // SIGABRT -- -[SwiftObject doesNotRecognizeSelector:]
    }
}

checkType(Bus<String>())
like image 978
Said Sikira Avatar asked Feb 23 '15 15:02

Said Sikira


People also ask

How can I check if an object is of a given type in Swift?

Checking TypeUse the type check operator ( is ) to check whether an instance is of a certain subclass type. The type check operator returns true if the instance is of that subclass type and false if it's not.

Is type of class Swift?

Type classes, also known as extension interfaces, are usually represented in Swift as protocols with associated types and/or Self requirements. They are groups of functions that operate on generic type parameters and are governed by algebraic laws.

What is generic class in Swift?

Generic code enables you to write flexible, reusable functions and types that can work with any type, subject to requirements that you define. You can write code that avoids duplication and expresses its intent in a clear, abstracted manner.


2 Answers

The problem here is your thinking of Bus as a concrete thing. It really isn't. Bus<String> is. Bus<Int> is too. But Bus isn't, at least not in the same sense. You need to know what T is.

Really, what you want is to write something like this:

func checkType<T>(object: AnyObject) {
    if let foo = object as? Bus<T> {
        println("Bus<T>")
    }
}

But if you try and use it, you'll get an error:

// error: Argument for generic parameter 'T' could not be inferred.
checkType(myBus)

Unlike in other languages, you can't write checkType<String>(myBus). But the following might do what you're looking for:

func checkType<T>(object: AnyObject, T.Type) {
    if let foo = object as? Bus<T> {
        println("Bus<T>")
    }
}

checkType(myBus,String.self)

This fixes what T is for any Bus<T> and will work correctly.

You might object that you don't want to specify what T is. However, instead, this leads to the question... once you've figured out that object is some kind of Bus, what are you going to do then? Are you planning on calling methods on it, or passing it as an argument to other functions? Chances are what you're trying to achieve can be better done with a generic function and protocol constraints, rather than using AnyObject and casting.

like image 137
Airspeed Velocity Avatar answered Sep 28 '22 11:09

Airspeed Velocity


In swift 2.x you can use a protocol to achieve this, as you attempted without error:

protocol Busish {
  func doSomething() -> Void
}

class Bus<T> : Busish {
  func doSomething() {
    print(self)
  }
}

func with_any_bus(obj:AnyObject) {
  if let b = obj as? Busish {
    b.doSomething()
  }
}

with_any_bus(Bus<Int>());
with_any_bus(Bus<String>());

output:

swiftblah.Bus<Swift.Int>
swiftblah.Bus<Swift.String>

This may or may not be helpful to you specifically, since you seem to be using 1.2, but maybe someone else who stumbles on this question will find it useful.

like image 22
Doug Avatar answered Sep 28 '22 10:09

Doug