【问题标题】:Swift type inference and type checking issueSwift 类型推断和类型检查问题
【发布时间】:2016-01-27 20:32:45
【问题描述】:

我不是在寻找一个答案,比如如何正确地做到这一点,而是为什么会发生这种情况。

代码如下:

func isInt(param: AnyObject?) {
    if let value = param as? Int {
        print(value)
    } else {
        print("Not Int")
    }

    if let value = param {
        if value is Int {
            print(value)
        } else {
            print("Not Int")
        }
    }
}

let a:AnyObject? = 1.2
let b:Float? = 1.2
let c:Double? = 1.2

isInt(a)
isInt(b)
isInt(c)

我理解在第一个 if 循环中,param 被强制转换为 Int,然后打印出 1

但是为什么在第二个if 循环中,if value is Int 为真,然后打印出1.2

【问题讨论】:

  • 在您的 b 案例中,let value = paramvalue 桥接到 NSNumber 类型。对于NSNumbervalue is Int 将始终为真。
  • @JAL 我刚刚查找了NSNumber 文档。不展开并执行if param is Int,它是true 并打印相同的值。同样的理由也适用吗?
  • 添加了未桥接值的答案。

标签: swift casting swift2 optional anyobject


【解决方案1】:

看看https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html,具体是:

Int、UInt、Float、Double 和 Bool 等 Swift 数值结构类型的实例不能用 AnyObject 类型表示,因为 AnyObject 只表示类类型的实例。但是,当桥接到 Foundation 启用时,Swift 数值可以作为 NSNumber 类的桥接实例分配给 AnyObject 类型的常量和变量。

我们可以在 Playground 中看到这一点:

let value = 1.2
value.dynamicType                   //Double.Type
value is Int                        //false
let castValue = value as AnyObject
castValue.dynamicType               //__NSCFNumber.Type (a private framework class, part of the NSNumber class cluster)
//NSNumber is bridged to Int, UInt, Float, Double, and Bool so `is` tests for those types will return `true`
castValue is Int                    //true
castValue is Float                  //true
//NSNumber is not bridged to String so an `is` test will return `false`
castValue is String                 //false

【讨论】:

    【解决方案2】:

    在您的 b 情况下,let value = paramvalue 桥接到 NSNumber 类型。对于NSNumbervalue is Int 将始终为真。

    对于未桥接的值:

    a is Int // always true, AnyObject bridges to NSNumber here
    b is Int // false, cast from Float to Int always fails
    c is Int // false, cast from Double to Int always fails
    

    此答案假定 Foundation 已导入。没有 Foundation,您的作业将失败。

    【讨论】:

      【解决方案3】:

      好吧,如果您执行以下操作,似乎它:

      func isInt(param: AnyObject?) {
      
          if let value = param {
              if value is Double {
                  print("I'm a double")
              }
          if value is Int{
                  print("I'm an int")
              }else {
                  print("Not Int")
              }
          }
      }
      

      它将为所有三个打印“I'm a double”,并为所有三个打印“I'm an int”。似乎当它进入 if 语句时,它会将值桥接到 NSNumber,这对于任何 NSNumber 类型都是正确的。

      但是,假设您执行以下操作:

      if let value = param {
              if value is String {
                  print("I'm a String")
              } 
              if value is Int{
                  print("I'm an int")
              }else {
                  print("Not Int")
              }
          }
      }
      

      由于String不是NSNumber类型,所以会跳转到if值为Int的NSNumber类型并返回值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-17
        • 2016-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多