【问题标题】:How can this AnyObject? has boolValue property这个 AnyObject 怎么可能?具有 boolValue 属性
【发布时间】:2016-01-10 04:20:46
【问题描述】:

我已经用 Swift 编写了一个 NSURL 扩展。

extension NSURL {
  var isDir : Bool {
    do {
      var isDir : AnyObject?
      try self.getResourceValue(&isDir, forKey: NSURLIsDirectoryKey)
      if let result = isDir?.boolValue {
        return result
      } else {
        return false
      }
    } catch {
      return false
    }
  }
}

这行得通。但是我发现有些人首先将指针(在这种情况下为isDIR)“投射”到NSNumber。例如:

我发现没有文档说 AnyObject 符合 BooleanType 协议。那么我在 Swift 中的代码是如何工作的呢?

【问题讨论】:

    标签: swift


    【解决方案1】:

    Command-点击AnyObject你会找到答案:

    /// The protocol to which all classes implicitly conform.
    ///
    /// When used as a concrete type, all known `@objc` methods and
    /// properties are available, as implicitly-unwrapped-optional methods
    /// and properties respectively, on each instance of `AnyObject`.  For
    /// example:
    ///
    ///     class C {
    ///       @objc func getCValue() -> Int { return 42 }
    ///     }
    ///
    ///     // If x has a method @objc getValue()->Int, call it and
    ///     // return the result.  Otherwise, return nil.
    ///     func getCValue1(x: AnyObject) -> Int? {
    ///       if let f: ()->Int = x.getCValue { // <===
    ///         return f()
    ///       }
    ///       return nil
    ///     }
    ///
    ///     // A more idiomatic implementation using "optional chaining"
    ///     func getCValue2(x: AnyObject) -> Int? {
    ///       return x.getCValue?() // <===
    ///     }
    ///
    ///     // An implementation that assumes the required method is present
    ///     func getCValue3(x: AnyObject) -> Int { // <===
    ///       return x.getCValue() // x.getCValue is implicitly unwrapped. // <===
    ///     }
    ///
    /// - SeeAlso: `AnyClass`
    @objc public protocol AnyObject {
    }
    

    因此,您可以在 AnyObject 实例上调用任何 @objc 方法。

    如果你输入

    let a: AnyObject?
    

    在游乐场然后:

    a?.
    

    自动完成将显示您可以调用的方法的完整列表。而且它巨大

    【讨论】:

    • 你可以跳过演员表。请务必使用可选绑定,因为如果底层对象类型不存在该方法,则将返回 nil
    • 谢谢。但是在这种情况下,如果isDir 不是nil,那它一定是NSNumber,对吧? (isDir as? NSNumber)?.boolValue 也有一个演员表和一个展开,它可能效率较低吗?
    • 您可能仍想像if let result = (isDir as? NSNumber)?.boolValue { 那样写它,因为它向您的读者记录了您期望发生的事情,但在功能上您可以跳过演员表。
    【解决方案2】:

    getResourceValue(_ *value*:forKey:) 的文档表明 _ *value*: 是一个 AutoreleasingUnsafeMutablePointer&lt;AnyObject?&gt; 类型,这意味着它基本上是一个 void 指针,只要它是正确的类型,就可以转换为任何类型。因此,将isDir 直接转换为Bool 将起作用,因为这基本上就是布尔类型:

    let boolResult: Bool = isDir as! Bool
    

    只是作为直接转换工作,因为它是一个 void 类型。

    【讨论】:

      【解决方案3】:

      除了 vacawama 的回答之外,Swift 文档的措辞有点令人困惑。它说对于AnyObject

      @objc 符号可用作隐式展开的可选方法和 属性。

      您可能认为这意味着所有内容都已隐式展开,但事实并非如此。 methods 可以作为隐式解包的选项使用,但 properties 类型都可以作为选项使用。因此,虽然在 AnyObject 上调用方法通常是不安全的,但访问属性是安全的。

      例如,

      let str = "Hello!" as NSString
      let any = str as AnyObject
      str.firstObject // compiler error, firstObject is an NSArray property
      any.firstObject // nil
      

      这就是您可以安全地致电boolValue 的原因。它从NSNumber 导入,其类型更改为Bool?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-31
        • 1970-01-01
        • 1970-01-01
        • 2017-02-12
        相关资源
        最近更新 更多