如何解开 Swift 选项?

问题描述 投票:0回答:8

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

这个主题似乎很混乱,我只是想了解所有方法以及它们如何有用。

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

var optionalString: String?

var implicitOptionalString: String!

打开两者的方法有哪些?另外,在展开过程中使用

!
?
有什么区别?

swift option-type
8个回答
70
投票

有很多相似之处,但也有一些差异。

(常规)可选

  • 声明:

    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

    • 使用新简写
      if let opt { ... someFunc(opt) ... } // no error
  • 安全链接:

    var x = opt?.property // x is also Optional, by extension

  • 安全合并零值:

    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

  • 安全合并零值:

    var x = opt ?? nonOpt


13
投票

自 Beta 5 以来,我们还有新的合并运算符 (??):

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

如果可选值为 != nil,则它被展开,否则使用运算符右侧的值


4
投票

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

// 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

希望有帮助:)


2
投票

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

示例:

var myString: Int? = 55
myString = nil

问号表示它可能具有零值。

但是如果你这样说:

var myString : Int = 55
myString = nil

会显示错误。

现在要检索您需要解开它的值:

print(myString!)

但是如果你想自动解开:

var myString: Int! = 55

然后:

print(myString)

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


1
投票

在 Swift 5.7 中安全地解开选项 ⛑

不同的技术(按偏好顺序)

使用适合工作的正确工具:

  1. 可选链接
  2. guard let
  3. if let
  4. 无合并运算符

在 Swift 中,有很多方法可以安全地解开可选值。我在上述偏好中订购技术的原因:

  1. 只有在确实需要的情况下,我们才应该打开选项。在这种情况下,我们不需要解开它并且可以使用可选链接。例如
    let value = optional?.value
  2. Guard 语句有助于在存在前提条件时尽早退出流程。通过减少嵌套级别,它在许多情况下是最干净的解决方案。
  3. if let
    对于顺序逻辑来说可能更具可读性。在某些情况下,当我们不想退出函数但继续在展开块之外执行附加逻辑时,
    if let
    guard
    更具可读性。
    if let
    非常灵活,也可以使用与
    guard
    语句类似的语法。
  4. 我们可以使用多个保护语句在使用多个选项之前对其进行解包,甚至可以使用
    ,
    &&
    ||
    在单个
    guard
    中检查多个条件。
  5. Nil 合并运算符可以很好地使用默认值来干净地展开选项:
    ??
    。但不要过度使用它们,因为使用
    guard
    通常可以更清楚地提前退出。
  6. 我概述了
    if let
    guard let
    的改进语法(在 Swift 5.7 中更加清晰)。
  7. 强制解包或 IUO(隐式解包选项)可能会导致运行时崩溃。它们由
    !
    表示,并且是 iOS 中的反模式,除非是测试套件的一部分,因为如果可选选项是
    nil
    ,它们可能会崩溃。在这种情况下,我们没有利用 Swift 相对于 Objective-C 改进的类型系统。在测试中,我们不关心干净的代码,因为测试不会在生产中运行,并且它们的目的已被包含。

if let
guard

的新语法
var x: EnumExample?

if let x {
   print(x.rawValue) // No longer optional
}

// We can still explicitly name the `if let` value if we want.
if let value = x {
    print(value.rawValue)
}

guard let x else {
    return
}
print(x.rawValue) // No longer optional

guard let value = x else {
    return
}
print(value.rawValue)

print(x?.rawValue ?? 0) // Unwrap with nil coalescing

注意:我还发现可选链接是展开选项的一种干净替代方案,并且对于我们只需要检查是否存在的情况,使用

 x != nil
就足够了。但这超出了 unwrapping 选项的问题范围。


1
投票
There is only seven ways to unwrap an optional in Swift

    var x : String? = "Test"
1,Forced unwrapping — unsafe.

    let a:String = x!
2,Implicitly unwrapped variable declaration — unsafe in many cases.

    var a = x!
3,Optional binding — safe.
if let a = x {
  print("x was successfully unwrapped and is = \(a)")
  }
4,Optional chaining — safe.

    let a = x?.count
5,Nil coalescing operator — safe.

    let a = x ?? ""
6,Guard statement — safe.

    guard let a = x else {
  return
}
7,Optional pattern — safe.

    if case let a? = x {
  print(a)
}

0
投票

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

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

0
投票

使用绑定安全解包的代码示例:

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
}
© www.soinside.com 2019 - 2024. All rights reserved.