Нет. Objective- C не может работать со структурами Swift, кроме специальных мостовых.
struct ?: Equatable { }
let dictionary = ["moo": ?()]
dictionary == dictionary // true
NSDictionary(dictionary: dictionary).isEqual(to: dictionary) // false
Прямое использование AnyHashable
также не поможет справиться со всем, но это лучше NSDictionary
подход.
public extension Equatable {
/// Equate two values of unknown type.
static func equate(_ any0: Any, _ any1: Any) -> Bool {
guard
let equatable0 = any0 as? Self,
let equatable1 = any1 as? Self
else { return false }
return equatable0 == equatable1
}
}
typealias Hashables = [String: AnyHashable?]
let dictionary: Hashables = ["a": nil, "b": 3, "c": true]
Hashables.equate(dictionary, dictionary) // true
Если этого недостаточно ...
/// A type-erased equatable value.
///
/// An `Equatable` instance is stored as a "`Cast`".
/// Only instances that can be cast to that type can be `==`'d with the `AnyEquatable`.
public struct AnyEquatable<Cast> {
public init<Equatable: Swift.Equatable>(_ equatable: Equatable) throws {
equals = try equatable.getEquals()
cast = equatable as! Cast
}
private let equals: (Cast) -> Bool
private let cast: Cast
}
extension AnyEquatable: Swift.Equatable {
public static func == (equatable0: Self, equatable1: Self) -> Bool {
equatable0 == equatable1.cast
}
}
public extension AnyEquatable {
static func == (equatable: Self, cast: Cast) -> Bool {
equatable.equals(cast)
}
static func == (cast: Cast, equatable: Self) -> Bool {
equatable.equals(cast)
}
}
public extension Equatable {
/// A closure that equates another instance to this intance.
/// - Parameters:
/// - _: Use the metatype for `Castable` to avoid explicit typing.
/// - Throws: `CastError.impossible` if a `Castable` can't be cast to `Self`.
func getEquals<Castable>(_: Castable.Type = Castable.self) throws -> (Castable) -> Bool {
if let error = CastError(self, desired: Castable.self)
{ throw error }
return { self == $0 as? Self }
}
}
/// An error that represents casting gone wrong. ?♀️?
public enum CastError: Error {
/// An undesired cast is possible.
case possible
/// An desired cast is not possible.
case impossible
}
public extension CastError {
/// `nil` if an `Instance` can be cast to `Desired`. Otherwise, `.impossible`.
init?<Instance, Desired>(_: Instance, desired _: Desired.Type) {
self.init(Instance.self, desired: Desired.self)
}
/// `nil` if a `Source` can be cast to `Desired`. Otherwise, `.impossible`.
init?<Source, Desired>(_: Source.Type, desired _: Desired.Type) {
if Source.self is Desired.Type
{ return nil }
self = .impossible
}
/// `nil` if an `Instance` cannot be cast to `Undesired`. Otherwise, `.possible`.
init?<Instance, Undesired>(_: Instance, undesired _: Undesired.Type) {
self.init(Instance.self, undesired: Undesired.self)
}
/// `nil` if a `Source` cannot be cast to `Undesired`. Otherwise, `.possible`.
init?<Source, Undesired>(_: Source.Type, undesired _: Undesired.Type) {
guard Source.self is Undesired.Type
else { return nil }
self = .possible
}
}
let dictionary: [String: AnyEquatable<Any>] = try [
"a": .init(Double?.none), "b": .init(3), "c": .init(true)
]
dictionary == dictionary // true