Swift 3 - How to verify class type of object

Van Du Tran picture Van Du Tran · Nov 2, 2016 · Viewed 59.7k times · Source

This line of code used to work with Swift 2, but now is incorrect in Swift 3.

if gestureRecognizer.isMember(of: UITapGestureRecognizer) { }

I get this error: Expected member name or constructor call after type name.

What is the correct way to use isMember(of:)?

Answer

Alexander picture Alexander · Nov 2, 2016

Most likely, you'll want to not only check the type, but also cast to that type. In this case, use:

if let gestureRecognizer as? UITapGestureRecognizer { }
else { /* not a UITapGestureRecognizer */ }

Swift casting operators

These operators are only available in Swift, but still work when dealing with Objective C types.

  • The as operator

    • The as operator performs a cast when it is known at compile time that the cast always succeeds, such as upcasting or bridging. Upcasting lets you use an expression as an instance of its type’s supertype, without using an intermediate variable.

    • This is the most preferable operator to use, when possible. It guarentees success, without worrying about unwrapping an optional or risking a crash.
  • The as? operator

    • The as? operator performs a conditional cast of the expression to the specified type. The as? operator returns an optional of the specified type. At runtime, if the cast succeeds, the value of expression is wrapped in an optional and returned; otherwise, the value returned is nil. If casting to the specified type is guaranteed to fail or is guaranteed to succeed, a compile-time error is raised.

    • This is the second most preferable operator to use. Use it to safely handle the case in which a casting operator can't be performed.

  • The as! operator

    • The as! operator performs a forced cast of the expression to the specified type. The as! operator returns a value of the specified type, not an optional type. If the cast fails, a runtime error is raised. The behavior of x as! T is the same as the behavior of (x as? T)!.

    • This is the least preferable operator to use. I strongly advise against abusing it. Attempting to cast an expression to an incompatible type crashes your program.


Swift type checking

If you merely want to check the type of an expression, without casting to that type, then you can use these approaches. They are only available in Swift, but still work when dealing with Objective C types.

  • The is operator

    • The is operator checks at runtime whether the expression can be cast to the specified type. It returns true if the expression can be cast to the specified type; otherwise, it returns false
    • Works on any Swift type, including Objective C types.
    • Swift equivalent of isKind(of:)
  • Using type(of:)

    • Unlike the is operator, this can be used to check the exact type, without consideration for subclasses.
    • Can be used like: type(of: instance) == DesiredType.self
    • Swift equivalent of isMember(of:)

Legacy (Objective C) methods for checking types

These are all methods on NSObjectProtocol. They can be used in Swift code, but they only apply work with classes that derive from NSObjectProtocol (such as subclasses of NSObject). I advise against using these, but I mention them here for completeness

  • isKind(of:)

    • Returns a Boolean value that indicates whether the receiver is an instance of given class or an instance of any class that inherits from that class
    • Avoid this in Swift, use is operator instead.
  • isMember(of:)

    • Returns a Boolean value that indicates whether the receiver is an instance of a given class
    • Avoid this in Swift, use type(of: instance) == DesiredType.self instead.
  • conforms(to:)

    • Returns a Boolean value that indicates whether the receiver conforms to a given protocol.
    • Avoid this in Swift, use is operator instead.