您如何打开Swift选项?

lp0sw83n  于 2022-12-10  发布在  Swift
关注(0)|答案(7)|浏览(201)

如何正确地展开普通和隐式可选项?
在这个主题中似乎有混乱,我只想有一个参考的所有方式和他们是如何有用的。
目前有两种方法可以创建可选项:

var optionalString: String?

var implicitOptionalString: String!

这两种方法都有哪些?另外,在解包过程中使用!?有什么区别?

bfhwhh0e

bfhwhh0e1#

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

(常规)可选

  • 声明: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
  • 使用new shorthandif let opt { ... someFunc(opt) ... } // 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
rsl1atfo

rsl1atfo2#

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

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

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

ujv3wf0j

ujv3wf0j3#

我创建了一种方法来展开可选值:

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

希望对你有帮助:)

5sxhfpxr

5sxhfpxr4#

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

var myString: Int? = 55
myString = nil

问号表示它可能具有零值。
但如果你这样陈述:

var myString : Int = 55
myString = nil

它将显示错误。
现在要检索需要展开的值:

print(myString!)

但如果要自动展开:

var myString: Int! = 55

然后道:

print(myString)

不需要拆开 Package ,希望能有帮助。

ntjbwcob

ntjbwcob5#

您也可以为特定类型创建扩展,并使用默认值安全地展开。

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

xnifntxz6#

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

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
}
wsewodh2

wsewodh27#

在Swift 5.7中 * 安全地 * 展开可选选项

不同技术(按优先顺序)

使用适合工作的工具:
1.可选链接

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

if letguard的新语法

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

注意:我还发现Optional chaining是一个简单的替代解包选项的方法,对于我们只需要检查存在性的示例,使用x != nil就足够了。

相关问题