Anyobject Try Cast to Equatable

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 UIViewControllers (and we know that UIViewControllers 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



Leave a reply



Submit