How to Check the Type of a Variable Against Another Variable in Swift

How to determine the type of a variable in Swift

You can get a reference to the type object of a value by using the .dynamicType property. This is equivalent to Python's type() function, and is mentioned in the Swift documentation under Language Reference: Types: Metatype Type.

var intArray = [1, 2, 3]
let typeOfArray = intArray.dynamicType

With this type object, we are able to create a new instance of the same array type.

var newArray = typeOfArray()
newArray.append(5)
newArray.append(6)
println(newArray)
[5, 6]

We can see that this new value is of the same type ([Int]) by attempting to append a float:

newArray.append(1.5)
error: type 'Int' does not conform to protocol 'FloatLiteralConvertible'

If we import Cocoa and use an array literal with mixed types, we can see that an NSArray is created:

import Cocoa

var mixedArray = [1, "2"]
let mixedArrayType = mixedArray.dynamicType

var newArray = mixedArrayType()
var mutableArray = newArray.mutableCopy() as NSMutableArray

mutableArray.addObject(1)
mutableArray.addObject(1.5)
mutableArray.addObject("2")

println(mutableArray)
(1, "1.5", 2)

However, at this point there does not seem to be any general way to generate a string description of a type object, so this may not serve the debugging role that you were asking about.

Types derived from NSObject do have a .description() method, as is used in SiLo's answer,

println(mixedArrayType.description())
__NSArrayI

However this is not present on types such as Swift's built-in arrays.

println(typeOfArray.description())
error: '[Int].Type' does not have a member named 'description'

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 to get type of a variable in swift

You can check the type of any variable using is keyword.

var a = 0
var b = "demo"
if (a is Int) {
print("It's an Int")
}

if (b is String) {
print("It's a String")
}

To compare any complex type, you can use below method:

if type(of: abc) == type(of: def) {
print("matching type")
} else {
print("something else")
}

How to observe a variable from another variable?

As mentioned in the comments, you can make your array a computed property. That resulting array will be what you display in ForEach.

See inline comments for explanations.

class Clients: ObservableObject {
@Published var items : [ClientItem] = [
.init(id: "1", name: "Z", phone: "1", email: "c"),
.init(id: "2", name: "Y", phone: "2", email: "b"),
.init(id: "3", name: "X", phone: "3", email: "a", isVisited: true)
]

enum FilterType {
case none, id, name, visited, notVisited
}

@Published var filterType : FilterType = .none //what type of filter is active

var itemsOrderedByName: [ClientItem] {
items.sorted { (client1, client2) -> Bool in
let client1 = client1.name
let client2 = client2.name
return (client1.localizedCaseInsensitiveCompare(client2) == .orderedAscending)
}
}

var itemsOrderedById: [ClientItem] {
items.sorted { (client1, client2) -> Bool in
let client1 = client1.id
let client2 = client2.id
return (client1.localizedCaseInsensitiveCompare(client2) == .orderedAscending)
}
}

var itemsVisited: [ClientItem] {
items.filter { item in
return item.isVisited == true
}
}

var itemsNotVisited: [ClientItem] {
items.filter { item in
return item.isVisited == false
}
}

var filteredItems : [ClientItem] { //return an array based on the current filter type
switch filterType {
case .none:
return items
case .id:
return itemsOrderedById
case .name:
return itemsOrderedByName
case .visited:
return itemsVisited
case .notVisited:
return itemsNotVisited
}
}
}

struct ContentView: View {
@StateObject var clients = Clients()
@State private var showAddClient = false
@State private var showFilterSheet = false

var body: some View {
NavigationView {
List {
ForEach(clients.filteredItems) { item in //iterate over the filtered elements
HStack {
VStack(alignment: .leading) {
Text(item.name).font(.headline)
Text(item.id)
Text(item.isVisited ? "Visited" : "Not visited")
}

Spacer()

VStack(alignment: .trailing) {
Link(item.phone, destination: URL(string: "tel:\(item.phone)")!)
Text(item.email)
}
}
}
.onDelete(perform: removeItems)
}
.navigationTitle("Dummy")
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button("Filter") {
showFilterSheet = true
}
.confirmationDialog("Select filter", isPresented: $showFilterSheet) {
Button("ID") {
clients.filterType = .id //set the filter type (same for the other types of buttons)
}
Button("Name") {
clients.filterType = .name
}
Button("Visited") {
clients.filterType = .visited
}
Button("No visitados") {
clients.filterType = .notVisited
}
Button("Cancel", role: .cancel) {
clients.filterType = .none
}
} message: {
Text("Filter by")
}
}

ToolbarItem(placement: .navigationBarTrailing) {
Button {
showAddClient = true
} label: {
Image(systemName: "plus")
}
}
}
}
}

func removeItems(at offsets: IndexSet) {
//we can't just use the index any more, because of the filter. So, find the corresponding item based on the current filter and then delete the item from the original array with a matching id
if let offset = offsets.first {
let item = clients.filteredItems[offset]
clients.items.removeAll { $0.id == item.id }
}
}
}

how to check the type of a variable in swift

You can do this with the is operator.
Example code:

var test: AnyObject

test = 12.2

if test is Double {
println("Double type")
} else if test is Int {
println("Int type")
} else if test is Float {
println("Float type")
} else {
println("Unkown type")
}

According to Apple docs:

Checking Type

Use 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 is not.

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

Swift 3 version:

type(of: yourObject)

How do I print the type or class of a variable in Swift?

Update September 2016

Swift 3.0: Use type(of:), e.g. type(of: someThing) (since the dynamicType keyword has been removed)

Update October 2015:

I updated the examples below to the new Swift 2.0 syntax (e.g. println was replaced with print, toString() is now String()).

From the Xcode 6.3 release notes:

@nschum points out in the comments that the Xcode 6.3 release notes show another way:

Type values now print as the full demangled type name when used with
println or string interpolation.

import Foundation

class PureSwiftClass { }

var myvar0 = NSString() // Objective-C class
var myvar1 = PureSwiftClass()
var myvar2 = 42
var myvar3 = "Hans"

print( "String(myvar0.dynamicType) -> \(myvar0.dynamicType)")
print( "String(myvar1.dynamicType) -> \(myvar1.dynamicType)")
print( "String(myvar2.dynamicType) -> \(myvar2.dynamicType)")
print( "String(myvar3.dynamicType) -> \(myvar3.dynamicType)")

print( "String(Int.self) -> \(Int.self)")
print( "String((Int?).self -> \((Int?).self)")
print( "String(NSString.self) -> \(NSString.self)")
print( "String(Array<String>.self) -> \(Array<String>.self)")

Which outputs:

String(myvar0.dynamicType) -> __NSCFConstantString
String(myvar1.dynamicType) -> PureSwiftClass
String(myvar2.dynamicType) -> Int
String(myvar3.dynamicType) -> String
String(Int.self) -> Int
String((Int?).self -> Optional<Int>
String(NSString.self) -> NSString
String(Array<String>.self) -> Array<String>

Update for Xcode 6.3:

You can use the _stdlib_getDemangledTypeName():

print( "TypeName0 = \(_stdlib_getDemangledTypeName(myvar0))")
print( "TypeName1 = \(_stdlib_getDemangledTypeName(myvar1))")
print( "TypeName2 = \(_stdlib_getDemangledTypeName(myvar2))")
print( "TypeName3 = \(_stdlib_getDemangledTypeName(myvar3))")

and get this as output:

TypeName0 = NSString
TypeName1 = __lldb_expr_26.PureSwiftClass
TypeName2 = Swift.Int
TypeName3 = Swift.String

Original answer:

Prior to Xcode 6.3 _stdlib_getTypeName got the mangled type name of a variable. Ewan Swick's blog entry helps to decipher these strings:

e.g. _TtSi stands for Swift's internal Int type.

Mike Ash has a great blog entry covering the same topic.

How can you quickly view a variable type in Xcode and Swift?

Alt-click on the variable does the thing in my case most of the time.

Swift variable comparison where type is not known

Expanding on the comments already made to the question: You should make
the class generic, so that it can be used with String or Int
items. What you need is that the items can be compared with ==,
i.e. that the type is Equatable.

The class declaration would then be

public class SearchOption<T : Equatable> {
// ...
}

and all occurrences of AnyObject have to be replaced by T.

The isSelected method simplifies to

public func isSelected(selectedOption: T) -> Bool {
if self.selectedOption != nil {
return self.selectedOption!.contains( { $0 == selectedOption })
}
return false
}

which can be further simplified using optional chaining
and the nil-coalescing operator ??:

public func isSelected(selectedOption: T) -> Bool {
return self.selectedOption?.contains( { $0 == selectedOption }) ?? false
}

Similarly:

public func removeSelectedItem(selectedOption: T) -> Void {
self.selectedOption = self.selectedOption?.filter( { $0 != selectedOption } )
}

For String items you would then create an instance of the class
with

let make = SearchOption<String>(title: "Make", allowAny: true, allowMultiple: true, dependencies: nil)


Related Topics



Leave a reply



Submit