Swift 3 - How to Verify Class Type of Object

How to get the object type in Swift3

Expanding on @jglasse's answer, you can get the type of an object by using

let theType = type(of: someObject)

You can then get a string from that by

let typeString = String(describing: type)

Or in one line:

let typeString = String(describing: type(of: someObject))

Swift 3: How to *specify* class of object, ruling out parent memberships?

You can use something like:

if type(of: self) == Parent.self {
// this only runs for exact type matches, not subclasses
}

That checks for equality of the types rather than polymorphic conformance of the instance (i.e. self is Parent)

Checking if an object is a given type in Swift

If you want to check against a specific type you can do the following:

if let stringArray = obj as? [String] {
// obj is a string array. Do something with stringArray
}
else {
// obj is not a string array
}

You can use "as!" and that will throw a runtime error if obj is not of type [String]

let stringArray = obj as! [String]

You can also check one element at a time:

let items : [Any] = ["Hello", "World"]
for obj in items {
if let str = obj as? String {
// obj is a String. Do something with str
}
else {
// obj is not a String
}
}

How do you find out the type of an object (in Swift)?

Swift 3 version:

type(of: yourObject)

How to check whether an object is kind of a dynamic class type in swift?

Personally, I think @JeremyP's suggestion to use Mirror is the best; though I would make a couple of tweaks to it:

/// Conditionally cast `x` to a given dynamic metatype value, taking into consideration
/// class inheritance hierarchies.
func conditionallyCast(_ x: T, to destType: U.Type) -> U? {

if type(of: x) is AnyClass && destType is AnyClass { // class-to-class

let isCastable = sequence(
first: Mirror(reflecting: x), next: { $0.superclassMirror }
)
.contains { $0.subjectType == destType }

return isCastable ? (x as! U) : nil
}

// otherwise fall back to as?
return x as? U
}

Here we're using sequence(first:next:) to create a sequence of metatypes from the dynamic type of x through any superclass metatypes it might have (probably the first use of the function I've seen that doesn't look awful :P). In addition, we're falling back to doing an as? cast when we know we're not doing a class-to-class cast, which allows the function to also work with protocol metatypes.

Then you can simply say:

extension Sequence {
func ofType(_ metatype: T.Type) -> [T] {
return flatMap { conditionallyCast($0, to: metatype) }
}
}

protocol P {}
class Animal {}
class Mammal: Animal {}
class Monkey: Mammal, P {}
class Pig: Mammal {}
class Human: Mammal, P {}

let animals = [Monkey(), Pig(), Human(), Mammal(), Animal()]

let animalType: Animal.Type = Mammal.self
print(animals.ofType(animalType)) // [Monkey, Pig, Human, Mammal]

print(animals.ofType(P.self)) // [Monkey, Human]

Another option, assuming you're on an Apple platform (i.e have access to the Objective-C runtime), is to use the the Objective-C metaclass method isSubclass(of:) in order to check if a given metatype is equal, or is a subclass of another:

import Foundation

/// Conditionally cast `x` to a given dynamic metatype value, taking into consideration
/// class inheritance hierarchies.
func conditionallyCast(_ x: T, to destType: U.Type) -> U? {

let sourceType = type(of: x)

if let sourceType = sourceType as? AnyClass,
let destType = destType as? AnyClass { // class-to-class

return sourceType.isSubclass(of: destType) ? (x as! U) : nil
}

// otherwise fall back to as?
return x as? U
}

This works because on Apple platforms, Swift classes are built on top of Obj-C classes – and therefore the metatype of a Swift class is an Obj-C metaclass object.

Better way to check the instance is kind from list of classes?

If I think about it logically, it would make a lot more sense to define a superclass / protocol for them, something like this:

class MyClassNumber { }

class MyClassOne: MyClassNumber { }
class MyClassTwo: MyClassNumber { }
class MyClassLetter { }

let one = MyClassOne()
let two = MyClassTwo()
let letter = MyClassLetter()

if one is MyClassNumber {
// TRUE
}

if two is MyClassNumber {
// TRUE
}

if letter is MyClassLetter {
// FALSE
}

Don't see any use case for yours



Related Topics



Leave a reply



Submit