Использование перечисления Swift для просмотра номеров тегов без rawValue
У меня есть целочисленное перечисление, которое я хотел бы использовать для viewWithTag(_:)
число, но это дает мне ошибку "Невозможно преобразовать значение типа 'viewTags' в ожидаемый тип аргумента 'Int'", хотя и перечисление, и номер тега необходимы в viewWithTag(_:)
является Int
,
Это довольно просто, и я могу заставить его работать, если я использую rawValue
собственность, но это более грязно и громоздко, чем мне бы хотелось.
enum viewTags: Int {
case rotateMirroredBtn
case iPhone6SP_7P_8P
case iPhoneX_Xs
case iPhoneXs_Max
case iPhone_Xr
case unknown
}
// error on if statement "Cannot convert value of type 'viewTags' to expected argument type 'Int'"
if let tmpButton = self.view.viewWithTag(viewTags.rotateMirroredBtn) as? UIButton {
tmpButton.removeFromSuperview()
}
2 ответа
Вы можете легко добавить расширение на UIView
сделать преобразование для вас. Вам просто нужно использовать универсальный параметр, чтобы ограничить аргумент тем, что вы можете получить Int
от.
extension UIView
{
/**
Returns the view’s nearest descendant (including itself) whose `tag`
matches the raw value of the given value, or `nil` if no subview
has that tag.
- parameter tag: A value that can be converted to an `Int`.
*/
func firstView <Tag : RawRepresentable> (taggedBy tag: Tag) -> UIView?
where Tag.RawValue == Int
{
let intValue = tag.rawValue
return self.viewWithTag(intValue)
}
}
Ограничение T : RawRepresentable where T.RawValue == Int
может быть выполнено вашим Int
Перечисление
Непатентованная форма тоже проста: func firstView(taggedBy viewTag: ViewTag) -> UIView?
Кроме того, вы также можете добавить метод для применения необработанного значения "составного" значения к представлению:
func applyTag <Tag : RawRepresentable> (_ tag: Tag)
where Tag.RawValue == Int
{
self.tag = tag.rawValue
}
(К сожалению, нет возможности записать это как свойство, например, var composedTag: Tag where Tag : RawRepresentable, Tag.RawValue == Int
потому что вычисляемое свойство не может создать свой собственный общий контекст, как метод.)
Я, как и оригинальный плакат, не предпочитаю использовать футляр rawValue
в коде, поэтому я добавил свойства вычисляемого типа в свои перечисления. Я использую Xcode v11.3.1 и Swift v5.1.3.
Например, многие из написанных мною модульных тестов использовали "магические" значения для создания IndexPath для табличных представлений с таким кодом:
let activeIndexPath = IndexPath(row: 0, section: 0)
let finishedIndexPath = IndexPath(row: 0, section: 1)
Я не хотел этого делать, хотя это улучшение по сравнению с "магическими" значениями:
let activeIndexPath = IndexPath(row: 0, section: TableViewSection.active.rawValue)
let finishedIndexPath = IndexPath(row: 0, section: TableViewSection.finished.rawValue)
Меня больше всего беспокоит тестируемая часть табличного представления, поэтому я придумал это перечисление, которое использует свойства вычисляемого типа для получения Int rawValues:
enum TableViewSection: Int {
case active
case finished
static var sectionActive: Int { return Self.active.rawValue }
static var sectionFinished: Int { return Self.finished.rawValue }
}
Теперь я могу создать IndexPath следующим образом:
let indexPathActive = IndexPath(row: 0, section: TableViewSection.sectionActive)
Обратной стороной является то, что вам нужно вычисляемое свойство с одинаковым именем для каждого случая, но конечный результат более нагляден на сайте вызова (хотя я предполагаю, что код, который использует rawValue, также является описательным), и теперь мне не нужно запомните, какое значение Int использовать для каждого конкретного раздела табличного представления, и мне больше не нужно использовать "магические" значения, что, как мы все знаем, плохо.
Надеюсь, это поможет!
Единственное, что вы упускаете rawValue
, Просто замени viewTags.rotateMirroredBtn
с viewTags.rotateMirroredBtn.rawValue
как это:
if let tmpButton = self.view.viewWithTag(viewTags.rotateMirroredBtn.rawValue) as? UIButton {
tmpButton.removeFromSuperview()
}