Downcasting optionals in Swift: as? Type, or as! Type?

前端 未结 9 1689
耶瑟儿~
耶瑟儿~ 2020-11-29 17:32

Given the following in Swift:

var optionalString: String?
let dict = NSDictionary()

What is the practical difference between the following

9条回答
  •  渐次进展
    2020-11-29 18:01

    To clarify what vacawama said, here is an example...

    Swift 3.0:

    import UIKit
    
    let str_value:    Any   = String("abc")!
    let strOpt_value: Any?  = String("abc")!
    let strOpt_nil:   Any?  = (nil as String?)
    let int_value:    Any   = Int(1)
    let intOpt_value: Any?  = Int(1)
    let intOpt_nil:   Any?  = (nil as Int?)
    
    // as String
    //str_value     as String // Compile-Time Error: 'Any' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
    //strOpt_value  as String // Compile-Time Error: 'Any?' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
    //strOpt_nil    as String // Compile-Time Error: 'Any?' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
    //int_value     as String // Compile-Time Error: 'Any' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
    //intOpt_value  as String // Compile-Time Error: 'Any?' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
    //intOpt_nil    as String // Compile-Time Error: 'Any?' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
    
    // as? String
      str_value     as? String // == "abc"
      strOpt_value  as? String // == "abc"
      strOpt_nil    as? String // == nil
      int_value     as? String // == nil
      intOpt_value  as? String // == nil
      intOpt_nil    as? String // == nil
    
    // as! String
      str_value     as! String // == "abc"
      strOpt_value  as! String // == "abc"
    //strOpt_nil    as! String // Run-Time Error: unexpectedly found nil while unwrapping an Optional value.
    //int_value     as! String // Run-Time Error: Could not cast value of type 'Swift.Int' to 'Swift.String'.
    //intOpt_value  as! String // Run-Time Error: Could not cast value of type 'Swift.Int' to 'Swift.String'.
    //intOpt_nil    as! String // Run-Time Error: unexpectedly found nil while unwrapping an Optional value.
    
    // as String?
    //str_value     as String? // Compile-Time Error: cannot convert value of type 'Any' to type 'String?' in coercion
    //strOpt_value  as String? // Compile-Time Error: 'Any?' is not convertible to 'String?'; did you mean to use 'as!' to force downcast?
    //strOpt_nil    as String? // Compile-Time Error: 'Any?' is not convertible to 'String?'; did you mean to use 'as!' to force downcast?
    //int_value     as String? // Compile-Time Error: cannot convert value of type 'Any' to type 'String?' in coercion
    //intOpt_value  as String? // Compile-Time Error: 'Any?' is not convertible to 'String?'; did you mean to use 'as!' to force downcast?
    //intOpt_nil    as String? // Compile-Time Error: 'Any?' is not convertible to 'String?'; did you mean to use 'as!' to force downcast?
    
    // as? String?
    //str_value     as? String? // Compile-Time Error: cannot downcast from 'Any' to a more optional type 'String?'
      strOpt_value  as? String? // == "abc"
      strOpt_nil    as? String? // == nil
    //int_value     as? String? // Compile-Time Error: cannot downcast from 'Any' to a more optional type 'String?'
      intOpt_value  as? String? // == nil
      intOpt_nil    as? String? // == nil
    
    // as! String?
    //str_value     as! String? // Compile-Time Error: cannot downcast from 'Any' to a more optional type 'String?'
      strOpt_value  as! String? // == "abc"
      strOpt_nil    as! String? // == nil
    //int_value     as! String? // Compile-Time Error: cannot downcast from 'Any' to a more optional type 'String?'
    //intOpt_value  as! String? // Run-Time Error: Could not cast value of type 'Swift.Int' to 'Swift.String'.
      intOpt_nil    as! String? // == nil
    
    // let _ = ... as String
    //if let _ = str_value    as String { true } // Compile-Time Error: 'Any' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
    //if let _ = strOpt_value as String { true } // Compile-Time Error: 'Any?' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
    //if let _ = strOpt_nil   as String { true } // Compile-Time Error: 'Any?' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
    //if let _ = int_value    as String { true } // Compile-Time Error: 'Any' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
    //if let _ = intOpt_value as String { true } // Compile-Time Error: 'Any?' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
    //if let _ = intOpt_nil   as String { true } // Compile-Time Error: 'Any?' is not convertible to 'String'; did you mean to use 'as!' to force downcast?
    
    // let _ = ... as? String
    if let _ = str_value    as? String { true } // true
    if let _ = strOpt_value as? String { true } // true
    if let _ = strOpt_nil   as? String { true } // false
    if let _ = int_value    as? String { true } // false
    if let _ = intOpt_value as? String { true } // false
    if let _ = intOpt_nil   as? String { true } // false
    
    // let _ = ... as! String
    //if let _ = str_value    as! String { true } // Compile-Time Error: initializer for conditional binding must have Optional type, not 'String'
    //if let _ = strOpt_value as! String { true } // Compile-Time Error: initializer for conditional binding must have Optional type, not 'String'
    //if let _ = strOpt_nil   as! String { true } // Compile-Time Error: initializer for conditional binding must have Optional type, not 'String'
    //if let _ = int_value    as! String { true } // Compile-Time Error: initializer for conditional binding must have Optional type, not 'String'
    //if let _ = intOpt_value as! String { true } // Compile-Time Error: initializer for conditional binding must have Optional type, not 'String'
    //if let _ = intOpt_nil   as! String { true } // Compile-Time Error: initializer for conditional binding must have Optional type, not 'String'
    
    // let _ = ... as String?
    //if let _ = str_value    as String? { true } // Compile-Time Error: cannot convert value of type 'Any' to type 'String?' in coercion
    //if let _ = strOpt_value as String? { true } // Compile-Time Error: 'Any?' is not convertible to 'String?'; did you mean to use 'as!' to force downcast?
    //if let _ = strOpt_nil   as String? { true } // Compile-Time Error: 'Any?' is not convertible to 'String?'; did you mean to use 'as!' to force downcast?
    //if let _ = int_value    as String? { true } // Compile-Time Error: cannot convert value of type 'Any' to type 'String?' in coercion
    //if let _ = intOpt_value as String? { true } // Compile-Time Error: 'Any?' is not convertible to 'String?'; did you mean to use 'as!' to force downcast?
    //if let _ = intOpt_nil   as String? { true } // Compile-Time Error: 'Any?' is not convertible to 'String?'; did you mean to use 'as!' to force downcast?
    
    // let _ = ... as? String?
    //if let _ = str_value    as? String? { true } // Compile-Time Error: cannot downcast from 'Any' to a more optional type 'String?'
      if let _ = strOpt_value as? String? { true } // true
      if let _ = strOpt_nil   as? String? { true } // true
    //if let _ = int_value    as? String? { true } // Compile-Time Error: cannot downcast from 'Any' to a more optional type 'String?'
      if let _ = intOpt_value as? String? { true } // false
      if let _ = intOpt_nil   as? String? { true } // true
    
    // let _ = ... as! String?
    //if let _ = str_value    as! String? { true } // Compile-Time Error: cannot downcast from 'Any' to a more optional type 'String?'
      if let _ = strOpt_value as! String? { true } // true
      if let _ = strOpt_nil   as! String? { true } // false
    //if let _ = int_value    as! String? { true } // Compile-Time Error: cannot downcast from 'Any' to a more optional type 'String?'
    //if let _ = intOpt_value as! String? { true } // Run-Time Error: Could not cast value of type 'Swift.Int' to 'Swift.String'.
      if let _ = intOpt_nil   as! String? { true } // false
    

    Swift 2.0:

    import UIKit
    
    let str:    AnyObject   = String("abc")
    let strOpt: AnyObject?  = String("abc")
    let strNil: AnyObject?  = (nil as String?)
    let int:    AnyObject   = Int(1)
    let intOpt: AnyObject?  = Int(1)
    let intNil: AnyObject?  = (nil as Int?)
    
    str    as? String // == "abc"
    strOpt as? String // == "abc"
    strNil as? String // == nil
    int    as? String // == nil
    intOpt as? String // == nil
    intNil as? String // == nil
    
    str    as! String? // Compile-Time Error: Cannot downcast from 'AnyObject' to a more optional type 'String?'
    strOpt as! String? // == "abc"
    strNil as! String? // == nil
    int    as! String? // Compile-Time Error: Cannot downcast from 'AnyObject' to a more optional type 'String?'
    intOpt as! String? // Run-Time Error: Could not cast value of type '__NSCFNumber' to 'NSString'
    intNil as! String? // == nil
    

提交回复
热议问题