使用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()
}

您可以很容易地在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值,也不必再使用"魔术"值,我们都知道这是一件坏事。

希望能有所帮助!

相关内容

  • 没有找到相关文章

最新更新