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
Update Restkit 'Lcl_Rk.H' File Not Found in Rklog.H
Where's the Difference Between Setobject:Forkey: and Setvalue:Forkey: in Nsmutabledictionary
Developing for iOS Device in Windows Environment with Flutter
How to Create a Delay in Swift
"From View Controller" Disappears Using Uiviewcontrollercontexttransitioning
Swift Filter Dictionary Error: Cannot Assign a Value of Type '[(_, _)]' to a Value of Type '[_:_]'
How to Use Iboutletcollection to Connect Multiple Uiimageviews to the Same Outlet
How to Change Locale Programmatically with Swift
How to Get an Iso 8601 Date on iOS
How to Change Inside Background Color of Uisearchbar Component on iOS
Ibeacon: Didrangebeacons Stops Getting Called, Must Reset Device for It to Work Again
How to Capitalize Each Word in a String Using Swift iOS
iOS 8 Sdk: Modal Uiwebview and Camera/Image Picker
Crashlytics: "We'Re Missing a Dsym to Process Crashes"
Automatic Preferred Max Layout Width Is Not Available on iOS Versions Prior to 8.0