【问题标题】:Logging a Swift enum using NSLog使用 NSLog 记录 Swift 枚举
【发布时间】:2014-06-05 13:36:50
【问题描述】:

我正在尝试记录一个枚举:

enum CKAccountStatus : Int {
    case CouldNotDetermine
    case Available
    case Restricted
    case NoAccount
}

NSLog("%i", CKAccountStatus.Available)

编译器抱怨:

Type 'CKAccountStatus' does not conform to protocol 'CVarArg'

为什么?我试图转换值:

NSLog("%i", CKAccountStatus.Available as Int)

但这也不行:

Cannot convert the expression's type '()' to type 'String'

【问题讨论】:

  • 你试过println吗?
  • 我做了,它打印出(Enum Value)。正确,但不是很有帮助:)

标签: swift nslog


【解决方案1】:

获取枚举的底层Int值:CKAccountStatus.Available.rawValue

枚举在 Swift 中并不是严格的整数,但如果它们是用底层类型声明的,你可以用 rawValue 来获得它——不管底层类型是什么。 (enum Foo: String 将为您提供 rawValue 等的字符串。)如果枚举没有基础类型,rawValue 将无能为力。在从 ObjC 导入的 API 中,使用 NS_ENUM 定义的任何枚举都具有底层整数类型(通常为 Int)。

如果您想打印更具描述性的枚举,您可以考虑对采用Printable 协议的枚举类型进行扩展。

【讨论】:

  • 我发现对于简单的Int 枚举,.hashValue 还可以让您访问Int 值。
  • 使用 hashValue 会滥用 API 合约。 Hashable 类型要求 hashValue 对于“相等”值是相同的,否则是唯一的,但不做其他保证......即使它巧合地返回与 rawValue 相同的 Int 枚举类型,你不要不知道将来不会改变。最好选择记录在案的 API 来做你想做的事,而不是碰巧做你想做的事。
【解决方案2】:

枚举实际上是不透明的。它可能有原始值,你可以得到;但许多枚举没有。 (您不必将枚举声明为具有类型,如果不声明,则没有原始值。)我要做的是给枚举一个 description 方法并显式调用它。

区分枚举当前值的唯一方法是通过 switch 语句,因此您的description 方法将处理每种情况,并且 switch 语句的每种情况都会返回不同的描述性值。

enum Suit {
    case Hearts, Diamonds, Spades, Clubs
    func description () -> String {
        switch self {
        case Hearts:
            return "hearts"
        case Diamonds:
            return "diamonds"
        case Spades:
            return "spades"
        case Clubs:
            return "clubs"
        }
    }
}

var suit = Suit.Diamonds
println("suit \(suit.description())")  // suit diamonds

【讨论】:

    【解决方案3】:

    这是我的方法:

    enum UserMode : String
    {
       case Hold = "Hold";
       case Selecting = "Selecting";
       case Dragging = "Dragging";
    }
    

    然后,每当我需要打印原始值时:

    //Assuming I have this declared and set somewhere
    var currentMode: UserMode = .Selecting;
    

    在做

    NSLog("CurrentMode \(_currMode.rawValue)");
    

    将打印:

    当前模式选择

    【讨论】:

      【解决方案4】:

      来自 Swift 文档:

      如果您熟悉 C,您就会知道 C 枚举将相关名称分配给一组整数值。 Swift 中的枚举更加灵活,并且不必为枚举的每个成员提供值。如果为每个枚举成员提供了一个值(称为“原始”值),则该值可以是字符串、字符或任何整数或浮点类型的值。

      因此,您不能尝试将其强制转换为和 Int。至于您的第一个问题,NSLog() 似乎正在寻找 C 变量类型的参数,这不适用于 Swift 枚举。

      【讨论】:

        【解决方案5】:

        我明白了,在 Swift 中枚举不是数字:

        与 C 和 Objective-C 不同,Swift 枚举成员没有分配一个 创建时的默认整数值。在指南针点 上面的例子,North、South、East 和 West 不隐式等于 0, 1、2和3。相反,不同的枚举成员是 完全成熟的价值观,具有明确定义的 CompassPoint 的类型。

        那么有没有办法轻松记录该值?啊,有:

        NSLog("%i", CKAccountStatus.Available.toRaw())
        

        【讨论】:

          【解决方案6】:

          您可以使用toRaw() 函数获取枚举的 Int-Value,如下所示:

          import Foundation
          
          enum CKAccountStatus : Int {
              case CouldNotDetermine
              case Available
              case Restricted
              case NoAccount
          }
          
          let block = {(status: Int) -> Void in
              NSLog("%d", status)
          }
          
          let status = CKAccountStatus.Available.toRaw()
          block(status) // prints "1"
          

          【讨论】:

          • 如何打印“可用”?
          【解决方案7】:

          对于我的错误枚举,我使用

          public var localizedDescription : String { return String(reflecting: self) }
          

          对于其他枚举,可以使用 CustomStringConvertible 协议

          public var description : String { return String(reflecting: self) }
          

          【讨论】:

            猜你喜欢
            • 2010-10-07
            • 2012-11-24
            • 2014-09-03
            • 2014-03-02
            • 2014-10-07
            • 2014-04-10
            • 1970-01-01
            • 1970-01-01
            • 2016-07-29
            相关资源
            最近更新 更多