AnyObject try cast to Equatable
Easy way - class stay NonGeneric, Generic only init
, and in GenericInit create isEquals method
class FieldItem: CustomStringConvertible, Equatable {
let value: Any?
let title: String
private let equals: (Any?) -> Bool
init<Value: Equatable>(title: String, value: Value?) {
func isEquals(_ other: Any?) -> Bool {
if let l = value, let r = other {
if let r = r as? Value {
return l == r
} else {
return false
}
} else {
return true
}
}
self.title = title
self.value = value
self.equals = isEquals
}
//CustomStringConvertible
var description: String { get { return title } }
//Equatable
public static func ==(lhs: FieldItem, rhs: FieldItem) -> Bool {
return ((lhs.title == rhs.title) && lhs.equals(rhs.value))
}
}
Common Equatable class on Swift
In lieu of existential types, you need to use a type eraser:
public struct AnyEquatable: Equatable {
public let value: Any
private let equals: (Any) -> Bool
public init<E: Equatable>(_ value: E) {
self.value = value
self.equals = { ($0 as? E) == value }
}
public static func == (lhs: AnyEquatable, rhs: AnyEquatable) -> Bool {
return lhs.equals(rhs.value) || rhs.equals(lhs.value)
}
}
example usage:
let items = [
AnyEquatable(1),
AnyEquatable(1.23),
AnyEquatable(true),
AnyEquatable("some string")
]
let desired = "some string"
let desiredAsAnyEquatable = AnyEquatable(desired)
let desiredDescription = String(reflecting: desired)
for item in items {
let itemDescription = String(reflecting: item.value)
let isEqualToDesired = item == desiredAsAnyEquatable
print("\(itemDescription) is \(isEqualToDesired ? "": "not ")equal to \(desiredDescription)")
}
Example output:
1 is not equal to "some string"
1.23 is not equal to "some string"
true is not equal to "some string"
"some string" is equal to "some string"
swift indexOf for [AnyObject] array
We need to cast the object we're testing to a UIViewController
, since we know that are array of controllers
is holding UIViewController
s (and we know that UIViewController
s conform to Equatable
.
extension PageViewController : UIPageViewControllerDelegate {
func pageViewController(pageViewController: UIPageViewController, willTransitionToViewControllers pendingViewControllers: [AnyObject]) {
if let controller = pendingViewControllers.first as? UIViewController {
self.nextIndex = self.viewControllers.indexOf(controller)
}
}
}
The logic behind the error is that in order for the indexOf
method to compare the object you pass in, it must compare them using the ==
operator. The Equatable
protocol specifies that the class has implemented this function, so this is what indexOf
requires its arguments conform to.
Objective-C doesn't have this same requirement, but the actual Objective-C implementation ends up meaning that the argument is compared with objects in the array using the isEqual:
method (which NSObject
and therefore all Objective-C classes implement).
How to compare Any value types
The only way to do this is with a function other than ==
that takes a type parameter, and then compares the values if they are both of that type:
func isEqual<T: Equatable>(type: T.Type, a: Any, b: Any) -> Bool {
guard let a = a as? T, let b = b as? T else { return false }
return a == b
}
Now, using your variables above, you can compare them like this:
var any1: Any = 1
var any2: Any = 1
var any3: Any = "test"
var any4: Any = "test"
isEqual(type: Int.self, a: any1, b: any2) // true
isEqual(type: Int.self, a: any2, b: any3) // false
isEqual(type: String.self, a: any3, b: any4) // true
Related Topics
Having Trouble with Nstimer (Swift)
How to I Turn Off the Ambient Light in Scene Kit (With Swift)
Different Colors for Bars in Barchart Depend on Value
What Does a "Do Statement" Without Catch Block Mean
How to Convert Text to Speech for Osx in Swift Playground
iOS Charts Remove Decimal from Yvalues
A Swiftier Way to Convert String to Unsafepointer<Xmlchar> in Swift 3 (Libxml2)
How to Turn Off Color Literals in Xcode
Cannot Subscript a Value of Type '[String:String]' with an Index of Type 'String'
Refreshing Auth Token with Moya
Getting an Issue with Upgrade to Xcode 10.2
Nsposixerrordomain When Binding to Socket on MACos 10.12
Module Compiled with Swift 4.0 Cannot Be Imported in Swift 3.0.2
How to Get the Kvc-String from Swift 4 Keypath
Pop View Controller Using Screen Edge Pan Gesture Recogniser Not Following the Thumb
How to Create a Nsmutabledictionary in Swift
How to Record My MAC's Internal Sound, Not the Microphone!, Using Avcapturesession