【问题标题】:How do you unwrap Swift optionals?你如何解开 Swift 选项?
【发布时间】:2014-08-08 03:16:47
【问题描述】:

如何正确解开普通和隐式选项?

这个话题似乎有些混乱,我只想对所有方法以及它们的用处有一个参考。

目前有两种创建可选项的方法:

var optionalString: String?

var implicitOptionalString: String!

有什么方法可以解开两者?另外,在解包过程中使用!? 有什么区别?

【问题讨论】:

  • 如果您询问具体情况而不是仅仅询问“似乎有混乱”,这个问题会更好。

标签: swift optional


【解决方案1】:

有很多相似之处,只有少数不同之处。

(常规)可选

  • 声明:var opt: Type?

  • 不安全展开:let x = opt!.property // error if opt is nil

  • 安全测试存在:if opt != nil { ... someFunc(opt!) ... } // no error

  • 通过绑定安全展开:if let x = opt { ... someFunc(x) ... } // no error

  • 安全链接:var x = opt?.property // x is also Optional, by extension

  • 安全合并 nil 值:var x = opt ?? nonOpt

隐式解包选项

  • 声明:var opt: Type!

  • 不安全展开(隐式):let x = opt.property // error if opt is nil

    • 通过分配不安全地展开:
      let nonOpt: Type = opt // error if opt is nil

    • 通过参数传递不安全地展开:
      func someFunc(nonOpt: Type) ... someFunc(opt) // error if opt is nil

  • 安全测试存在:if opt != nil { ... someFunc(opt) ... } // no error

  • 安全链接:var x = opt?.property // x is also Optional, by extension

  • 安全合并 nil 值:var x = opt ?? nonOpt

【讨论】:

    【解决方案2】:

    从 Beta 5 开始,我们还有新的合并运算符 (??):

    var a : Int?
    let b : Int = a ?? 0
    

    如果可选项是 != nil 则解包,否则使用运算符右侧的值

    【讨论】:

      【解决方案3】:

      我创建了一种解开可选值的方法:

      // MARK: - Modules
      import Foundation
      import UIKit
      import CoreData
      
      // MARK: - PROTOCOL
      protocol OptionalType { init() }
      
      // MARK: - EXTENSIONS
      extension String: OptionalType {}
      extension Int: OptionalType {}
      extension Double: OptionalType {}
      extension Bool: OptionalType {}
      extension Float: OptionalType {}
      extension CGFloat: OptionalType {}
      extension CGRect: OptionalType {}
      extension UIImage: OptionalType {}
      extension IndexPath: OptionalType {}
      extension Date: OptionalType {}
      extension UIFont: OptionalType {}
      extension UIColor: OptionalType {}
      extension UIViewController: OptionalType {}
      extension UIView: OptionalType {}
      extension NSMutableDictionary: OptionalType {}
      extension NSMutableArray: OptionalType {}
      extension NSMutableSet: OptionalType {}
      extension NSEntityDescription: OptionalType {}
      extension Int64: OptionalType {}
      extension CGPoint: OptionalType {}
      extension Data: OptionalType {}
      extension NSManagedObjectContext: OptionalType {}
      
      prefix operator ?*
      
      //unwrapping values
      prefix func ?*<T: OptionalType>( value: T?) -> T {
          guard let validValue = value else { return T() }
          return validValue
      }
      

      您也可以添加自定义数据类型。

      用法:-

      var myString = ?*str
      

      希望对你有帮助:)

      【讨论】:

      • 更不用说成为最好的方法了。这在很多方面都是错误的。
      • 你能详细说明一下吗? @Desdenova
      • 以整数为例,0 != nil
      • 在这两种情况下它都会返回 true。你可以空运行它。
      • 这是使用运算符的必要条件吗?来自 C#,我有一种下沉的感觉,我永远无法完全掌握 Swift 的循环语法。它有点功能性、有点程序性和有点面向对象的混合在一起。尽管我很鄙视 JS,但它的掠夺性语法要简单得多。
      【解决方案4】:

      可选类型意味着变量可能为 nil。

      例子:

      var myString: Int? = 55
      myString = nil
      

      问号表示它可能有 nil 值。

      但如果你这样说:

      var myString : Int = 55
      myString = nil
      

      它会显示错误。

      现在检索您需要解包的值:

      print(myString!)
      

      但如果你想自动解包:

      var myString: Int! = 55
      

      然后:

      print(myString)
      

      无需打开包装。希望它会有所帮助。

      【讨论】:

        【解决方案5】:

        您还可以为特定类型创建扩展并使用默认值安全地展开。我做了同样的事情:

        extension Optional where Wrapped == String {
            func unwrapSafely() -> String {
                if let value = self {
                    return value
                }
                return ""
            }
        }
        

        【讨论】:

          【解决方案6】:

          使用绑定安全展开的代码示例:

          let accountNumber = account.accountNumber //optional
          let accountBsb = account.branchCode //optional
          var accountDetails: String = "" //non-optional
          
          if let bsbString = account.branchCode, let accString = account.accountNumber {
              accountDetails = "\(bsbString) \(accString)" //non-optional
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-10-21
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多