【问题标题】:Swift 3 - How to verify class type of objectSwift 3 - 如何验证对象的类类型
【发布时间】:2017-03-16 06:15:27
【问题描述】:

这行代码曾经在 Swift 2 中工作,但现在在 Swift 3 中不正确。

if gestureRecognizer.isMember(of: UITapGestureRecognizer) { }

我收到此错误:预期的成员名称或类型名称后的构造函数调用。

isMember(of:)的正确使用方法是什么?

【问题讨论】:

  • 编译器为您提供了哪些修复? ;)
  • 这个if gestureRecognizer.isMember(of: UITapGestureRecognizer()) { } 不起作用。
  • 点击红色八边形,编译器会显示两个修复它(其中一个解决了你的问题:))
  • @VanDuTran 你的回答满意吗?

标签: ios swift3 casting type-inference


【解决方案1】:

很可能,您不仅要检查类型,还要强制转换为该类型。在这种情况下,请使用:

if let gestureRecognizer as? UITapGestureRecognizer { }
else { /* not a UITapGestureRecognizer */ }

Swift 转换运算符

这些运算符仅在 Swift 中可用,但在处理 Objective C 类型时仍然有效。

  • as 运算符

    • as 运算符在编译时知道转换总是成功时执行转换,例如向上转换或桥接。向上转型让您可以将表达式用作其类型超类型的实例,而无需使用中间变量。

    • 如果可能,这是最适合使用的运算符。它保证了成功,而不必担心打开可选选项或面临崩溃的风险。
  • as? 运算符

    • as? 运算符将表达式条件转换为指定类型。 as? 运算符返回指定类型的可选项。在运行时,如果转换成功,expression 的值被包裹在一个可选项中并返回;否则,返回值为nil。如果强制转换为指定的 type 保证失败或保证成功,则会引发编译时错误。

    • 这是第二个最好使用的运算符。使用它来安全处理无法执行铸造操作的情况。

  • as! 运算符

    • as! 运算符将表达式强制转换为指定类型。 as! 运算符返回指定type 的值,而不是可选类型。如果转换失败,则会引发运行时错误。 x as! T 的行为与(x as? T)! 的行为相同。

    • 这是最不推荐使用的运算符。我强烈建议不要滥用它。尝试将表达式转换为不兼容的类型会使您的程序崩溃。


Swift 类型检查

如果您只想检查表达式的类型,而不强制转换为该类型,那么您可以使用这些方法。它们仅在 Swift 中可用,但在处理 Objective C 类型时仍然有效。

  • is 运算符

    • is 运算符在运行时检查表达式是否可以转换为指定的类型。如果表达式可以转换为指定类型,则返回true;否则,它返回false
    • 适用于任何 Swift 类型,包括 Objective C 类型。
    • Swift 等效于 isKind(of:)
  • 使用type(of:)

    • is 运算符不同,它可用于检查确切的类型,无需考虑子类。
    • 可以像这样使用:type(of: instance) == DesiredType.self
    • Swift 等效于 isMember(of:)

用于检查类型的传统(Objective C)方法

这些都是NSObjectProtocol 上的方法。它们可以在 Swift 代码中使用,但它们仅适用于派生自 NSObjectProtocol 的类(例如 NSObject 的子类)。我建议不要使用这些,但为了完整起见,我在此提及它们

  • isKind(of:)

    • 返回一个布尔值,指示接收者是给定类的实例还是从该类继承的任何类的实例
    • 在 Swift 中避免这种情况,请改用 is 运算符。
  • isMember(of:)

    • 返回一个布尔值,指示接收器是否是给定类的实例
    • 在 Swift 中避免这种情况,请改用 type(of: instance) == DesiredType.self
  • conforms(to:)

    • 返回一个布尔值,指示接收器是否符合给定协议。
    • 在 Swift 中避免这种情况,请改用 is 运算符。

【讨论】:

  • 嗯,很奇怪。看起来字符串文字以某种方式与编译器混淆。 type(of: String()) == String.self 工作正常。如果您先分配它,它也可以工作...let f = type(of: ""); if f == String.self {}
  • @Hamish 嗯,很有趣。
  • 没问题 - 我保证,刚才的编辑是最后一个;)
  • @AlexZavatone 这些都行不通,也没有意义。 Swift 是一种静态类型语言。程序中的所有类型都必须在编译时解析。当您转换为type(of: myObj) 时,在编译时不知道您要转换为什么类型(因为myObj 可以是任何东西),因此它不会提供任何价值。如果您考虑一下,您可以期望在一个直到运行时才知道类型的变量上使用哪些方法/属性?
  • @xaphod 在编译时知道右手类型并不重要。重要的是它一种类型,无论是已知的(具体类型)还是未知的(直到运行时才知道的泛型)。将istType: Animal.Type 一起使用会失败,因为tType 是元类型object,而不是类型。你只需要一个通用的来解决你的问题。见gist.github.com/xaphod/…
【解决方案2】:

有几种方法可以检查对象的类。大多数情况下,您会希望像这样使用isas? 运算符:

let gestureRecognizer: UIGestureRecognizer = UITapGestureRecognizer()

// Using the is operator
if gestureRecognizer is UITapGestureRecognizer {
    // You know that the object is an instance of UITapGestureRecognizer,
    // but the compiler will not let you use UITapGestureRecognizer specific
    // methods or properties on gestureRecognizer because the type of the
    // variable is still UIGestureRecognizer
    print("Here")
}

// Using the as? operator and optional binding
if let tapGestureRecognizer = gestureRecognizer as? UITapGestureRecognizer {
    // tapGestureRecognizer is the same object as gestureRecognizer and is
    // of type UITapGestureRecognizer, you can use UITapGestureRecognizer
    // specific methods or properties.
    print("Here")
}

// Using the type(of:) global function
if type(of: gestureRecognizer) == UITapGestureRecognizer.self {
    // gestureRecognizer is an instance of UITapGestureRecognizer, but not any
    // of its subclasses (if gestureRecognizer was an instance of a subclass of
    // UITapGestureRecognizer, the body of this if would not execute).
    // This kind of check is rarely usefull, be sure this is really what you
    // want to do before you use it.
    print("Here")
}

// Using the isKind(of:) method
if gestureRecognizer.isKind(of: UITapGestureRecognizer.self) {
    // Like for the is operator, you know that the object is an instance of
    // UITapGestureRecognizer (or any subclass of UITapGestureRecognizer).
    // This is the Objective-C version of the is operator and will only work
    // on classes that inherit from NSObject, don't use it in Swift.
    print("Here")
}

// Using the isMember(of:) method
if gestureRecognizer.isMember(of: UITapGestureRecognizer.self) {
    // gestureRecognizer is an instance of UITapGestureRecognizer, but not
    // any of its subclasses.
    // This is the Objective-C version of type(of:) and will only work on
    // classes that inherit from NSObject, don't use it in Swift.
    print("Here")
}

【讨论】:

    【解决方案3】:

    您现在必须使用 .self 来引用类类型。

    let a = UITapGestureRecognizer()
    print (a.isMember(of: UIGestureRecognizer.self))
    

    还有:

    print (a is UITapGestureRecognizer)
    

    【讨论】:

      【解决方案4】:

      斯威夫特 3:

      if gestureRecognizer is UITapGestureRecognizer {
                  //It's a tap
      }
      

      【讨论】:

      • 如何检查是不是
      • @RakeshiOSDev 只需将语句括在括号中,前面有“!”比如 if !(gestureRecognizer is UITapGestureRecognizer)
      • 我读了“这是个陷阱”,当我重读它时,我感到非常难过。
      猜你喜欢
      • 2021-05-17
      • 1970-01-01
      • 2022-08-09
      • 1970-01-01
      • 2023-04-02
      • 2017-12-08
      • 2018-12-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多