【问题标题】:What is an optional value in Swift?Swift 中的可选值是什么?
【发布时间】:2014-07-23 02:36:22
【问题描述】:

来自Apple's documentation

您可以同时使用iflet 来处理可能丢失的值。这些值表示为可选项。可选值包含一个值或包含nil 以指示缺少该值。在值的类型后写一个问号(?),将值标记为可选。

为什么要使用可选值?

【问题讨论】:

标签: swift optional


【解决方案1】:

Swift 中的可选项是一种可以保存值或不保存值的类型。可选项是通过将? 附加到任何类型来编写的:

var name: String? = "Bertie"

可选(连同泛型)是最难理解的 Swift 概念之一。由于它们的编写和使用方式,很容易对它们是什么产生错误的认识。将上面的可选内容与创建普通字符串进行比较:

var name: String = "Bertie" // No "?" after String

从语法上看,可选字符串与普通字符串非常相似。它不是。可选字符串不是打开了某些“可选”设置的字符串。它不是一种特殊的字符串。字符串和可选字符串是完全不同的类型。

这里最重要的是要知道:可选项是一种容器。可选字符串是可能包含字符串的容器。可选的 Int 是可能包含 Int 的容器。将可选项视为一种包裹。在打开它之前(或用可选语言“解包”),您不会知道它是否包含某些内容。

您可以在 Swift 标准库中看到 how optionals are implemented,方法是在任何 Swift 文件中键入“可选”并 ⌘-单击它。这是定义的重要部分:

enum Optional<Wrapped> {
    case none
    case some(Wrapped)
}

Optional 只是 enum,它可以是以下两种情况之一:.none.some。如果是.some,则有一个关联值,在上面的示例中,它是String“Hello”。可选项使用泛型为关联值提供类型。可选字符串的类型不是String,而是Optional,或者更准确地说是Optional&lt;String&gt;

Swift 对可选项所做的一切都是让阅读和编写代码更加流畅的魔法。不幸的是,这掩盖了它实际工作的方式。稍后我会介绍一些技巧。

注意:我会经常谈论可选变量,但也可以创建可选常量。我用它们的类型标记所有变量,以便更容易理解正在创建的类型类型,但您不必在自己的代码中。


如何创建选项

要创建一个可选项,请在要包装的类型后附加?。任何类型都可以是可选的,甚至是您自己的自定义类型。类型和? 之间不能有空格。

var name: String? = "Bob" // Create an optional String that contains "Bob"
var peter: Person? = Person() // An optional "Person" (custom type)

// A class with a String and an optional String property
class Car {
var modelName: String // must exist
var internalName: String? // may or may not exist
}

使用选项

您可以将一个可选项与nil 进行比较,看看它是否有值:

var name: String? = "Bob"
name = nil // Set name to nil, the absence of a value
if name != nil {
    print("There is a name")
}
if name == nil { // Could also use an "else"
    print("Name has no value")
}

这有点令人困惑。这意味着可选是一件事或另一件事。它要么是 nil,要么是“Bob”。这不是真的,可选项不会转换成别的东西。将其与 nil 进行比较是一种使代码更易于阅读的技巧。如果一个可选项等于 nil,这仅表示枚举当前设置为 .none


只有可选项可以为 nil

如果您尝试将非可选变量设置为 nil,则会收到错误消息。

var red: String = "Red"
red = nil // error: nil cannot be assigned to type 'String'

另一种看待可选项的方式是作为普通 Swift 变量的补充。它们是保证有值的变量的对应物。 Swift 是一种谨慎的语言,它讨厌歧义。大多数变量都被定义为非可选变量,但有时这是不可能的。例如,想象一个视图控制器从缓存或网络加载图像。在创建视图控制器时,它可能有也可能没有该图像。无法保证 image 变量的值。在这种情况下,您必须将其设为可选。它以nil 开头,当检索到图像时,可选值会得到一个值。

使用可选项揭示了程序员的意图。与任何对象都可以为 nil 的 Objective-C 相比,Swift 需要您清楚何时可以缺少值以及何时保证存在。


要使用可选的,你“解包”它

不能使用可选的String 代替实际的String。要在可选项中使用包装的值,您必须将其解包。解开可选项的最简单方法是在可选项名称后添加!。这称为“强制展开”。它返回可选项内的值(作为原始类型),但如果可选项是nil,则会导致运行时崩溃。在打开包装之前,您应该确定有一个值。

var name: String? = "Bob"
let unwrappedName: String = name!
print("Unwrapped name: \(unwrappedName)")

name = nil
let nilName: String = name! // Runtime crash. Unexpected nil.

检查和使用可选的

因为在展开和使用可选项之前,您应该始终检查 nil,这是一种常见的模式:

var mealPreference: String? = "Vegetarian"
if mealPreference != nil {
    let unwrappedMealPreference: String = mealPreference!
    print("Meal: \(unwrappedMealPreference)") // or do something useful
}

在此模式中,您检查一个值是否存在,然后当您确定它存在时,您强制将其解包为一个临时常量以供使用。因为这是很常见的事情,Swift 提供了一个使用“if let”的快捷方式。这称为“可选绑定”。

var mealPreference: String? = "Vegetarian"
if let unwrappedMealPreference: String = mealPreference {
    print("Meal: \(unwrappedMealPreference)") 
}

这将创建一个临时常量(或变量,如果您将let 替换为var),其范围仅在if 的大括号内。因为必须使用像“unwrappedMealPreference”或“realMealPreference”这样的名称是一种负担,Swift 允许您重用原始变量名称,在括号范围内创建一个临时名称

var mealPreference: String? = "Vegetarian"
if let mealPreference: String = mealPreference {
    print("Meal: \(mealPreference)") // separate from the other mealPreference
}

这里有一些代码来演示使用了不同的变量:

var mealPreference: String? = "Vegetarian"
if var mealPreference: String = mealPreference {
    print("Meal: \(mealPreference)") // mealPreference is a String, not a String?
    mealPreference = "Beef" // No effect on original
}
// This is the original mealPreference
print("Meal: \(mealPreference)") // Prints "Meal: Optional("Vegetarian")"

可选绑定通过检查可选是否等于 nil 来工作。如果没有,它会将可选项解包到提供的常量中并执行块。在 Xcode 8.3 及更高版本 (Swift 3.1) 中,尝试打印像这样的可选项将导致无用的警告。使用可选的debugDescription 使其静音:

print("\(mealPreference.debugDescription)")

什么是可选的?

选件有两个用例:

  1. 可能失败的事情(我期待着什么,但我什么也没得到)
  2. 现在什么都不是但以后可能会出现的事情(反之亦然)

一些具体的例子:

  • 可以存在或不存在的属性,例如Person 类中的middleNamespouse
  • 一种可以返回值或不返回值的方法,例如在数组中搜索匹配项
  • 一种可以返回结果或得到错误且不返回任何内容的方法,例如尝试读取文件的内容(通常返回文件的数据)但文件不存在
  • 委托属性,不一定要设置,一般在初始化后设置
  • 用于类中的weak 属性。他们指向的东西可以随时设置为nil
  • 可能必须释放大量资源以回收内存
  • 当您需要一种方法来知道何时设置了一个值(数据尚未加载 > 数据)而不是使用单独的 dataLoaded Boolean

Objective-C 中不存在可选项,但有一个等效的概念,返回 nil。可以返回对象的方法可以返回 nil。这被认为意味着“没有有效的对象”,并且通常用来表示出现了问题。它仅适用于 Objective-C 对象,不适用于原语或基本 C 类型(枚举、结构)。 Objective-C 通常有专门的类型来表示这些值的缺失(NSNotFound 实际上是NSIntegerMaxkCLLocationCoordinate2DInvalid 表示无效坐标,-1 或一些负值也被使用)。编码人员必须了解这些特殊值,因此必须针对每种情况记录和学习它们。如果方法不能将nil 作为参数,则必须记录在案。在 Objective-C 中,nil 是一个指针,就像所有对象都被定义为指针一样,但 nil 指向一个特定的(零)地址。在 Swift 中,nil 是一个字面量,表示某种类型的缺失。


对比nil

你曾经可以使用任何可选的Boolean

let leatherTrim: CarExtras? = nil
if leatherTrim {
    price = price + 1000
}

在更新的 Swift 版本中,您必须使用 leatherTrim != nil。为什么是这样?问题是 Boolean 可以包装在一个可选项中。如果你有这样的Boolean

var ambiguous: Boolean? = false

它有两种“假”,一种没有值,一种有值但值为false。 Swift 讨厌模棱两可,所以现在你必须始终检查 nil 的可选项。

您可能想知道可选的Boolean 有什么意义?与其他选项一样,.none 状态可能表明该值是未知的。网络调用的另一端可能有一些东西需要一些时间来轮询。可选布尔值也称为“Three-Value Booleans


Swift 技巧

Swift 使用了一些技巧来允许可选项工作。考虑这三行普通的可选代码;

var religiousAffiliation: String? = "Rastafarian"
religiousAffiliation = nil
if religiousAffiliation != nil { ... }

这些行都不应该编译。

  • 第一行使用字符串文字设置一个可选字符串,两种不同的类型。即使这是 String 类型也不同
  • 第二行将一个可选字符串设置为 nil,两种不同的类型
  • 第三行将一个可选字符串与 nil 进行比较,两种不同的类型

我将介绍允许这些行工作的选项的一些实现细节。


创建一个可选的

使用? 创建一个可选的语法糖,由 Swift 编译器启用。如果你想长期这样做,你可以创建一个这样的可选:

var name: Optional<String> = Optional("Bob")

这会调用Optional 的第一个初始化程序public init(_ some: Wrapped),它从括号中使用的类型推断出可选的关联类型。

创建和设置可选的更长的方法:

var serialNumber:String? = Optional.none
serialNumber = Optional.some("1234")
print("\(serialNumber.debugDescription)")

将可选设置为nil

你可以创建一个没有初始值的可选,或者创建一个初始值为nil的可选(两者的结果相同)。

var name: String?
var name: String? = nil

允许选项等于nil 由协议ExpressibleByNilLiteral(以前称为NilLiteralConvertible)启用。可选项是使用Optional 的第二个初始化程序public init(nilLiteral: ()) 创建的。文档说您不应该将 ExpressibleByNilLiteral 用于除可选项之外的任何内容,因为这会改变代码中 nil 的含义,但可以这样做:

class Clint: ExpressibleByNilLiteral {
    var name: String?
    required init(nilLiteral: ()) {
        name = "The Man with No Name"
    }
}

let clint: Clint = nil // Would normally give an error
print("\(clint.name)")

相同的协议允许您将已创建的可选项设置为nil。虽然不推荐,但可以直接使用 nil 字面量初始化器:

var name: Optional<String> = Optional(nilLiteral: ())

将可选项与nil 进行比较

选项定义了两个特殊的“==”和“!=”运算符,您可以在Optional 定义中看到它们。第一个== 允许您检查是否有任何可选项等于nil。如果关联的类型相同,则设置为 .none 的两个不同的选项将始终相等。当您与 nil 进行比较时,Swift 在幕后创建一个具有相同关联类型的可选项,设置为 .none 然后使用它进行比较。

// How Swift actually compares to nil
var tuxedoRequired: String? = nil
let temp: Optional<String> = Optional.none
if tuxedoRequired == temp { // equivalent to if tuxedoRequired == nil
    print("tuxedoRequired is nil")
}

第二个== 运算符允许您比较两个选项。两者必须是相同的类型,并且该类型需要符合Equatable(允许将事物与常规“==”运算符进行比较的协议)。 Swift(大概)解开这两个值并直接比较它们。它还处理其中一个或两个选项为.none 的情况。请注意与 nil 文字比较之间的区别。

此外,它允许您将任何Equatable 类型与该类型的可选包装进行比较:

let numberToFind: Int = 23
let numberFromString: Int? = Int("23") // Optional(23)
if numberToFind == numberFromString {
    print("It's a match!") // Prints "It's a match!"
}

在幕后,Swift 在比较之前将非可选项包装为可选项。它也适用于文字 (if 23 == numberFromString {)

我说有两个 == 运算符,但实际上还有第三个可以让您将 nil 放在比较的左侧

if nil == name { ... }

命名选项

对于可选类型与非可选类型的命名不同,没有 Swift 约定。人们避免在名称中添加一些内容以表明它是可选的(如“optionalMiddleName”或“possibleNumberAsString”),并让声明表明它是可选类型。当你想命名一些东西来保存可选的值时,这会变得很困难。 “middleName”这个名字意味着它是一个字符串类型,所以当你从中提取字符串值时,你通常会得到像“actualMiddleName”或“unwrappedMiddleName”或“realMiddleName”这样的名称。使用可选绑定并重用变量名来解决这个问题。


官方定义

来自"The Basics" in the Swift Programming Language

Swift 还引入了可选类型,用于处理值的缺失。可选项要么说“有一个值,它等于 x”,要么说“根本没有值”。可选项类似于在 Objective-C 中使用带指针的 nil,但它们适用于任何类型,而不仅仅是类。 Optional 比 Objective-C 中的 nil 指针更安全、更有表现力,并且是 Swift 许多最强大功能的核心。

Optional 是 Swift 是一种类型安全语言的一个例子。 Swift 帮助你清楚你的代码可以使用的值的类型。如果您的部分代码需要一个字符串,类型安全会阻止您错误地传递一个 Int。这使您能够在开发过程中尽早发现并修复错误。


最后,这是一首 1899 年关于可选的诗:

昨天在楼梯上
我遇到了一个不在那里的人
他今天又不在了
我希望,我希望他离开

Antigonish


更多资源:

【讨论】:

  • @KaanDedeoglu 不幸的是,史蒂夫在很大程度上是可选的。他在这里,现在他不在了。
  • if myString 不再编译。你需要if myString != nil。见documentation
  • 对 ?和 !在网上找到的 Swift 中使用。谢谢
  • mateo 深入解释了 Optionals,深入浅出和简单的例子。
  • 谢谢你的解释,比苹果自己的文档清楚多了。
【解决方案2】:

让我们以NSError 为例,如果没有返回错误,您希望将其设为可选以返回 Nil。如果没有错误,给它赋值是没有意义的..

var error: NSError? = nil

这也允许你有一个默认值。因此,如果函数未传递任何内容,您可以将方法设置为默认值

func doesntEnterNumber(x: Int? = 5) -> Bool {
    if (x == 5){
        return true
    } else {
        return false
    }
}

【讨论】:

  • 句子“如果它是 nil,那么任何表达式的结果也是 nil”是完全错误的。 func isNil&lt;T&gt;(t: T?) -&gt; Bool { return t == nil } 将返回 true,即使表达式中有一个可选值 nil
  • 非常糟糕的代码示例。你就不能想点更好的吗?为什么不简单地return x == 5? 5 有什么特别之处?
  • 不,2 年前我想不出更好的办法。今天是的,但这是否说明问题?是的。感谢@Atomosk 的输入,它真的很有帮助。
【解决方案3】:

在 Swift 中你不能有一个指向 nil 的变量——没有指针,也没有空指针。但是在 API 中,您通常希望能够指示特定类型的值或缺少值 - 例如。我的窗口有代表吗?如果有,是谁? Optional 是 Swift 的类型安全、内存安全的方法。

【讨论】:

    【解决方案4】:

    我做了一个简短的回答,总结了以上大部分内容,以消除我作为初学者的不确定性:

    相对于Objective-C,Swift中没有变量可以包含nil,所以增加了Optional变量类型(变量以“?”为后缀):

        var aString = nil //error
    

    最大的区别是可选变量不直接存储值(就像普通的 Obj-C 变量那样)它们包含两种状态:“有一个值 " 或 "没有":

        var aString: String? = "Hello, World!"
        aString = nil //correct, now it contains the state "has nil"
    

    也就是说,您可以在不同的情况下检查这些变量:

    if let myString = aString? {
         println(myString)
    }
    else { 
         println("It's nil") // this will print in our case
    }
    

    通过使用“!”后缀,您还可以访问包含在其中的值,仅当这些值存在时。 (即不是nil):

    let aString: String? = "Hello, World!"
    // var anotherString: String = aString //error
    var anotherString: String = aString!
    
    println(anotherString) //it will print "Hello, World!"
    

    这就是为什么你需要使用“?”和 ”!”并且默认情况下不使用所有这些。 (这是我最大的困惑)

    我也同意上面的回答:可选类型不能用作布尔值

    【讨论】:

      【解决方案5】:

      在目标 C 中,没有值的变量等于 'nil'(也可以使用与 0 和 false 相同的 'nil' 值),因此可以在条件语句中使用变量(具有值的变量相同为 'TRUE',没有值的为 'FALSE')。

      Swift 通过提供“可选值”来提供类型安全。即它可以防止由于分配不同类型的变量而形成的错误。

      所以在 Swift 中,条件语句只能提供布尔值。

      var hw = "Hello World"
      

      这里,尽管 'hw' 是一个字符串,但它不能像在目标 C 中那样在 if 语句中使用。

      //This is an error
      
      if hw
      
       {..}
      

      为此,它需要创建为,

      var nhw : String? = "Hello World"
      
      //This is correct
      
      if nhw
      
       {..}
      

      【讨论】:

        【解决方案6】:

        可选值允许您显示不存在的值。有点像 SQL 中的 NULL 或 Objective-C 中的 NSNull。我想这将是一个改进,因为您甚至可以将其用于“原始”类型。

        // Reimplement the Swift standard library's optional type
        enum OptionalValue<T> {
            case None
            case Some(T)
        }
        var possibleInteger: OptionalValue<Int> = .None
        possibleInteger = .Some(100)”
        

        摘自:Apple Inc.“Swift 编程语言”。电子书。 https://itun.es/gb/jEUH0.l

        【讨论】:

        • nil 只是枚举常量OptionalValue&lt;T&gt;.None 的语法糖(其中T 是适合您使用nil 的上下文的类型)。 ?OptionalValue&lt;T&gt;.Some(T) 的快捷方式。
        【解决方案7】:

        可选表示 Swift 不完全确定该值是否对应于类型:例如,Int?表示 Swift 不完全确定该数字是否为 Int。

        要删除它,您可以使用三种方法。

        1) 如果你完全确定了类型,可以使用感叹号强制解包,如下所示:

        // Here is an optional variable:
        
        var age: Int?
        
        // Here is how you would force unwrap it:
        
        var unwrappedAge = age!
        

        如果你强制解包一个可选项并且它等于 nil,你可能会遇到这个崩溃错误:

        这不一定安全,所以如果你不确定类型和值,这里有一个方法可以防止崩溃:

        方法二和三可以防止这个问题。

        2) 隐式展开的可选

         if let unwrappedAge = age {
        
         // continue in here
        
         }
        

        请注意,展开后的类型现在是 Int,而不是 Int?

        3) 守卫声明

         guard let unwrappedAge = age else { 
           // continue in here
         }
        

        从这里,您可以继续使用展开的变量。如果您确定变量的类型,请确保仅强制展开(使用 !)。

        祝你的项目好运!

        【讨论】:

          【解决方案8】:

          当我开始学习Swift 时,很难理解为什么可选

          让我们这样想。 让我们考虑一个类Person,它有两个属性namecompany

          class Person: NSObject {
              
              var name : String //Person must have a value so its no marked as optional
              var companyName : String? ///Company is optional as a person can be unemployed that is nil value is possible
              
              init(name:String,company:String?) {
                  
                  self.name = name
                  self.companyName = company
                  
              }
          }
          

          现在让我们创建几个Person的对象

          var tom:Person = Person.init(name: "Tom", company: "Apple")//posible
          var bob:Person = Person.init(name: "Bob", company:nil) // also Possible because company is marked as optional so we can give Nil
          

          但我们不能将Nil 传递给name

          var personWithNoName:Person = Person.init(name: nil, company: nil)
          

          现在让我们谈谈我们为什么使用optional?。 让我们考虑一种情况,我们想在公司名称之后添加 Inc,例如apple 将是apple Inc。我们需要在公司名称后面加上Inc并打印出来。

          print(tom.companyName+" Inc") ///Error saying optional is not unwrapped.
          print(tom.companyName!+" Inc") ///Error Gone..we have forcefully unwrap it which is wrong approach..Will look in Next line
          print(bob.companyName!+" Inc") ///Crash!!!because bob has no company and nil can be unwrapped.
          

          现在让我们来研究一下为什么要使用 optional。

          if let companyString:String = bob.companyName{///Compiler safely unwrap company if not nil.If nil,no unwrap.
              
              print(companyString+" Inc") //Will never executed and no crash!!!
          }
          

          让我们用tom替换bob

          if let companyString:String = tom.companyName{///Compiler safely unwrap company if not nil.If nil,no unwrap.
              
              print(companyString+" Inc") //Will executed and no crash!!!
          }
          

          还有恭喜!我们已经妥善处理了optional?

          所以实现点是

          1. 如果变量可能是nil,我们会将其标记为可选
          2. 如果我们想在代码编译器的某个地方使用这个变量 提醒您,我们需要检查我们是否对该变量进行了适当的处理 如果它包含nil

          谢谢...快乐编码

          【讨论】:

            【解决方案9】:

            让我们尝试下面的代码Playground。我希望能清楚地知道什么是可选的以及使用它的原因。

            var sampleString: String? ///Optional, Possible to be nil
            
            sampleString = nil ////perfactly valid as its optional
            
            sampleString = "some value"  //Will hold the value
            
            if let value = sampleString{ /// the sampleString is placed into value with auto force upwraped.
            
                print(value+value)  ////Sample String merged into Two
            }
            
            sampleString = nil // value is nil and the
            
            if let value = sampleString{
            
                print(value + value)  ///Will Not execute and safe for nil checking
            }
            
            //   print(sampleString! + sampleString!)  //this line Will crash as + operator can not add nil
            

            【讨论】:

              【解决方案10】:

              来自https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html

              可选链是查询和调用当前可能为 nil 的可选的属性、方法和下标的过程。如果 optional 包含值,则属性、方法或下标调用成功;如果可选项为 nil,则属性、方法或下标调用返回 nil。多个查询可以链接在一起,如果链中的任何链接为 nil,则整个链都会优雅地失败。

              要深入了解,请阅读上面的链接。

              【讨论】:

                【解决方案11】:

                嗯……

                ? (可选) 表示您的变量可能包含 nil 值,而 ! (unwrapper) 表示您的变量在运行时使用(试图从中获取值)时必须具有内存(或值)。

                主要区别在于,当可选项为 nil 时,可选项链接会优雅地失败,而当可选项为 nil 时,强制解包会触发运行时错误。

                为了反映可以对 nil 值调用可选链接这一事实,可选链接调用的结果始终是可选值,即使您正在查询的属性、方法或下标返回非可选值也是如此。您可以使用此可选返回值来检查可选链接调用是否成功(返回的可选包含值),或者由于链中的 nil 值而未成功(返回的可选值为 nil)。

                具体来说,可选链接调用的结果与预期返回值的类型相同,但包装在可选中。当通过可选链接访问时,通常返回 Int 的属性将返回 Int?

                var defaultNil : Int?  // declared variable with default nil value
                println(defaultNil) >> nil  
                
                var canBeNil : Int? = 4
                println(canBeNil) >> optional(4)
                
                canBeNil = nil
                println(canBeNil) >> nil
                
                println(canBeNil!) >> // Here nil optional variable is being unwrapped using ! mark (symbol), that will show runtime error. Because a nil optional is being tried to get value using unwrapper
                
                var canNotBeNil : Int! = 4
                print(canNotBeNil) >> 4
                
                var cantBeNil : Int = 4
                cantBeNil = nil // can't do this as it's not optional and show a compile time error
                

                这里是详细的基础教程,由 Apple 开发者委员会提供:Optional Chaining

                【讨论】:

                  【解决方案12】:

                  Swift 中的可选项是一种可以保存值或不保存值的类型。可选项是通过将 ? 附加到任何类型来编写的:

                  var name: String?
                  

                  可以参考这个链接深入了解:https://medium.com/@agoiabeladeyemi/optionals-in-swift-2b141f12f870

                  【讨论】:

                    【解决方案13】:

                    有很多错误是由于人们试图使用未设置的值而导致的,有时这可能会导致崩溃,在目标 c 中尝试调用 nil 对象引用的方法将被忽略,所以有些你的一段代码没有执行,编译器或编写的代码无法告诉你为什么。一个可选参数让您拥有永远不会为零的变量,如果您尝试构建它,编译器可以在您的代码甚至有机会运行之前告诉您,或者您可以决定它适合未定义的对象,然后编译器会在您尝试编写未考虑到这一点的内容时告诉您。

                    在调用可能的 nil 对象的情况下,你可以直接去

                    object?.doSomthing()
                    

                    您已经向编译器和任何阅读您的代码的人明确表示,它的可能对象是 nil 并且什么都不会发生。有时你有几行代码你只想在值存在时出现,所以你可以这样做

                    if let obj = object {
                        obj.doSomthing()
                        doSomethingto(obj)
                    }
                    

                    这两个语句仅在对象是某物时才会执行,同样,如果它不是某物,您可能希望停止整个代码块的其余部分

                    guard let obj = object {
                        return
                    }
                    obj.doSomthing()
                    doSomethingto(obj)
                    

                    如果之后的所有内容仅在对象是某物时才适用,则阅读起来会更简单,另一种可能是您想使用默认值

                    let obj = object ?? <default-object>
                    obj.doSomthing()
                    doSomethingto(obj)
                    

                    现在 obj 将被分配给某个东西,即使它是该类型的默认值

                    选项在以下情况下很有用在设置之前它没有任何意义,我喜欢使用选项的一种方法是告诉我必须完成某些事情或者是否已经完成了例如

                    func eventFired() {
                        guard timer == nil else { return }
                        timer = scheduleTimerToCall(method, in: 60)
                    }
                    
                    func method() {
                        doSomthing()
                        timer = nil
                    }
                    

                    这个 sudo 代码可以多次调用 eventFired,但只有在第一次调用时才会安排计时器,一旦安排执行,它就会运行一些方法并将计时器设置回 nil,以便可以安排另一个计时器。

                    一旦您对处于未定义状态的变量有所了解,您就可以将其用于各种事情。

                    【讨论】:

                      【解决方案14】:

                      这是 Swift 中一个等效的可选声明:

                      var middleName: String?
                      

                      此声明创建了一个名为 middleName 的 String 类型的变量。 String 变量类型后面的问号 (?) 表示 middleName 变量可以包含一个可以是 String 或 nil 的值。任何查看此代码的人都会立即知道 middleName 可以为 nil。它是自我记录的!

                      如果您没有为可选常量或变量指定初始值(如上所示),则该值会自动为您设置为 nil。如果您愿意,可以将初始值显式设置为 nil:

                      var middleName: String? = nil
                      

                      更多详情请阅读以下链接

                      http://www.iphonelife.com/blog/31369/swift-101-working-swifts-new-optional-values

                      【讨论】:

                      • 使用这个,var middleName: String! = ""
                      猜你喜欢
                      • 2019-06-07
                      • 1970-01-01
                      • 1970-01-01
                      • 2020-05-17
                      • 2014-07-24
                      • 1970-01-01
                      • 1970-01-01
                      • 2015-12-04
                      • 1970-01-01
                      相关资源
                      最近更新 更多