使用Swift枚举作为不带rawValue的视图标记号

时间:2019-01-10 18:48:30

标签: swift cocoa-touch enums viewwithtag

我有一个整数枚举数,我想将其用于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()
}

3 个答案:

答案 0 :(得分: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,因为计算出的属性无法像方法那样创建自己的通用上下文。)

答案 1 :(得分:1)

我和原始张贴者一样,不喜欢在代码中使用案例的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值,而且我也不必再使用“魔术”值了,我们都知道这是一件坏事。

希望有帮助!

答案 2 :(得分:0)

您唯一缺少的是rawValue。像这样用viewTags.rotateMirroredBtn替换viewTags.rotateMirroredBtn.rawValue

if let tmpButton = self.view.viewWithTag(viewTags.rotateMirroredBtn.rawValue) as? UIButton { 
    tmpButton.removeFromSuperview()
}