Допустим, у нас есть два экземпляра UILabel
, которые для нас эквивалентны:
let label1 = UILabel()
label1.text = "Hello world"
let label2 = UILabel()
label2.text = "Hello world"
Допустим, два экземпляра находятся в массиве типа [UIView]
:
let views: [UIView] = [label1, label2]
Есть ли способ выполнить проверку на равенство, которая обнаружит, что эти два экземпляра UIView
эквивалентны, не зная заранее, к какому типу они относятся (и, следовательно, по каким общим свойствам сравнивать)?
(Любой способ использовать тот факт, что оба этих экземпляра имеют dynamicType
UILabel
и динамически проходят через свойства "ключ-значение" класса UILabel
и сравнивают каждое значение, которое можно сравнить ?)
Что происходит:
label1 == label2 // false
views[0] == views[1] // false
Что желаю:
areTheSame(label1, label2) // true
areTheSame(views[0], views[1]) // true
Мы ищем способ сравнить два отдельных экземпляра, поэтому мы не можем использовать ===
.
2 ответа
Swift не имеет отражения, поэтому это невозможно. Мы даже не можем получить список атрибутов.
Также обратите внимание, что для многих типов нет определения равенства. Даже сравнение двух значений с плавающей запятой является проблемой.
Именно поэтому у нас есть протокол Equatable
. Если вы хотите сравнивать типы, определите для них равенство. Это равенство может быть настолько глубоким, насколько необходимо, без необходимости какого-либо динамического (небезопасного) поведения.
Просто чтобы объяснить другой угловой случай, например, для UILabel
есть некоторые свойства, которые вы определенно не хотите сравнивать, а именно такие вещи, как nextResponder
или superview
. Попытка глубокого сравнения этих свойств фактически закончится циклом. Обычно невозможно сравнить два объекта на равенство, не зная точно, что следует и что не следует сравнивать.
Примерно так должно работать:
let views: [UIView] = [label1, label2]
func areTheSameLabel(view1: UIView, _ view2: UIView) -> Bool {
guard let label1 = view1 as? UILabel,
let label2 = view2 as? UILabel else { return false }
return label1.text = label2.text
}
print(areTheSameLabel(label1, label2)) // Should print "true"
print(areTheSameLabel(views[0], views[1])) // Should print "true"
В ответ на ваши комментарии я думаю, что лучший способ - это создать протокол:
protocol ViewEquatable {
var backgroundColor: UIColor? { get set }
var text: String? { get set }
// add any other properties you want to compare here...
}
Затем напишите функцию для их сравнения:
func ==<T: ViewComparable>(lhs: T, rhs: T) -> Bool {
return (lhs.backgroundColor == rhs.backgroundColor) &&
(lhs.text == rhs.text) &&
// whatever other comparison tests you need go here...
}
Что-то подобное, вероятно, ваш лучший вариант, хотя ваши требования слишком расплывчаты, чтобы дать исчерпывающий ответ ...
Похожие вопросы
Новые вопросы
swift
Swift — это язык программирования общего назначения, разработанный Apple Inc., впервые выпущенный в 2014 году для своих платформ и Linux. Swift имеет открытый исходный код. Используйте тег только для вопросов о языковых функциях или необходимости кода в Swift. Используйте теги [ios], [ipados], [macos], [watch-os], [tvos], [swiftui], [cocoa-touch] и [cocoa] для (не зависящих от языка) вопросов о платформах или рамки.