使用 Swift 枚举作为不带 rawValue 的视图标签编号
Using a Swift enum as view tag numbers without rawValue
我有一个整数枚举,我想将其用于 viewWithTag(_:)
数字,但它给我错误 "Cannot convert value of type 'viewTags' to expected argument type '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()
}
您可以轻松地在 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?
奖金,您还可以添加一个方法来 apply 将 "composed" 值的原始值应用到视图的:
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.
例如,我编写的许多单元测试都使用 "magic" 值来为 table 视图创建 IndexPath,代码如下:
let activeIndexPath = IndexPath(row: 0, section: 0)
let finishedIndexPath = IndexPath(row: 0, section: 1)
我不想这样做,尽管它比 "magic" 值有所改进:
let activeIndexPath = IndexPath(row: 0, section: TableViewSection.active.rawValue)
let finishedIndexPath = IndexPath(row: 0, section: TableViewSection.finished.rawValue)
我最关心的是我正在测试的 table 视图部分,所以我想出了这个枚举,它使用计算类型属性来获取 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 的代码也具有描述性) ,现在我不必记住 table 视图的每个特定部分要使用哪个 Int 值,而且我不必再使用 "magic" 值,我们都知道这是不好的东西。
希望对您有所帮助!
我有一个整数枚举,我想将其用于 viewWithTag(_:)
数字,但它给我错误 "Cannot convert value of type 'viewTags' to expected argument type '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()
}
您可以轻松地在 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?
奖金,您还可以添加一个方法来 apply 将 "composed" 值的原始值应用到视图的:
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.
例如,我编写的许多单元测试都使用 "magic" 值来为 table 视图创建 IndexPath,代码如下:
let activeIndexPath = IndexPath(row: 0, section: 0)
let finishedIndexPath = IndexPath(row: 0, section: 1)
我不想这样做,尽管它比 "magic" 值有所改进:
let activeIndexPath = IndexPath(row: 0, section: TableViewSection.active.rawValue)
let finishedIndexPath = IndexPath(row: 0, section: TableViewSection.finished.rawValue)
我最关心的是我正在测试的 table 视图部分,所以我想出了这个枚举,它使用计算类型属性来获取 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 的代码也具有描述性) ,现在我不必记住 table 视图的每个特定部分要使用哪个 Int 值,而且我不必再使用 "magic" 值,我们都知道这是不好的东西。
希望对您有所帮助!