我有一个整数枚举,我想将其用于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()
}
您可以很容易地在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 v1.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值,也不必再使用"魔术"值,我们都知道这是一件坏事。
希望能有所帮助!