Swift中的可选值是什么?

Swift中的可选值是什么?,swift,optional,Swift,Optional,发件人: 您可以同时使用if和let来处理可能缺少的值。这些值表示为可选值。可选值包含值或包含nil,以指示缺少该值。在值的类型后写一个问号(?),将该值标记为可选值 为什么要使用可选值?让我们以一个n错误为例,如果没有返回错误,您可以选择返回Nil。如果没有错误,给它赋值是没有意义的 var error: NSError? = nil 这也允许您有一个默认值。因此,如果函数没有传递任何内容,可以将方法设置为默认值 func doesntEnterNumber(x: Int? = 5) -&g

发件人:

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


为什么要使用可选值?

让我们以一个
n错误为例,如果没有返回错误,您可以选择返回Nil。如果没有错误,给它赋值是没有意义的

var error: NSError? = nil
这也允许您有一个默认值。因此,如果函数没有传递任何内容,可以将方法设置为默认值

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

在Swift中不能有指向
nil
的变量-没有指针,也没有空指针。但在API中,您通常希望能够指示特定类型的值或缺少值-例如,我的窗口是否有委托,如果有,是谁?选项是Swift的类型安全、内存安全的方式。可选值允许您显示没有值。有点像SQL中的NULL或Objective-C中的NSNull。我想这将是一个改进,因为您甚至可以将其用于“基本”类型

//重新实现Swift标准库的可选类型
枚举可选值{
无案例
案例(T)
}
var possibleInteger:OptionalValue=.None
可能整数=.Some(100)”

摘自:苹果公司《Swift编程语言》。iBooks

Swift中的可选类型是一种既可以保存值也可以不保存值的类型。选项是通过在任何类型后附加
来编写的:

var name: String? = "Bertie"
var name: String?
Optionals(以及泛型)是最难理解的Swift概念之一。由于它们是如何编写和使用的,很容易对它们产生错误的认识。将上述选项与创建普通字符串进行比较:

var name: String = "Bertie" // No "?" after String
从语法上看,可选字符串与普通字符串非常相似。不是。可选字符串不是启用了某些“可选”设置的字符串。这不是一种特殊的弦。字符串和可选字符串是完全不同的类型

这里有一件最重要的事情要知道:可选的是一种容器。可选字符串是可能包含字符串的容器。可选整数是可能包含整数的容器。请将可选整数视为一种包裹。在你打开它(或者用optionals语言“展开”)之前,你不知道它包含什么或什么

您可以通过在任何Swift文件中键入“可选”并⌘-点击它。以下是定义的重要部分:

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

使用选项 您可以将可选值与
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进行比较是一个使代码更易于阅读的技巧。如果可选值等于nil,则表示枚举当前设置为
.none


只有可选项可以为零 如果试图将非可选变量设置为nil,则会出现错误

var red: String = "Red"
red = nil // error: nil cannot be assigned to type 'String'
另一种看待期权的方式是作为普通Swift变量的补充。它们是保证有值的变量的对应项。斯威夫特是一种谨慎的语言,不喜欢含糊不清。大多数变量被定义为非可选变量,但有时这是不可能的。例如,假设一个视图控制器从缓存或网络加载图像。在创建视图控制器时,它可能有也可能没有该图像。无法保证image变量的值。在这种情况下,您必须将其设置为可选。它以
nil
开始,当检索图像时,可选的获取一个值

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

name = nil
let nilName: String = name! // Runtime crash. Unexpected nil.
使用可选选项可以揭示程序员的意图。与Objective-C相比,在Objective-C中,任何对象都可以为零,Swift需要您清楚地知道什么时候可以缺少值,什么时候可以保证存在值


若要使用可选文件,请将其“展开” 可选的
字符串
不能代替实际的
字符串
。要在可选文件中使用包装的值,必须将其展开。打开可选文件的最简单方法是添加
在可选名称之后。这称为“强制展开”。它返回optional中的值(作为原始类型),但如果optional为
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”的快捷方式。这称为“可选绑定”

这将创建一个临时常量(或变量,如果将
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)")

什么是可选的
print("\(mealPreference.debugDescription)")
let leatherTrim: CarExtras? = nil
if leatherTrim {
    price = price + 1000
}
var ambiguous: Boolean? = false
var religiousAffiliation: String? = "Rastafarian"
religiousAffiliation = nil
if religiousAffiliation != nil { ... }
var name: Optional<String> = Optional("Bob")
var serialNumber:String? = Optional.none
serialNumber = Optional.some("1234")
print("\(serialNumber.debugDescription)")
var name: String?
var name: String? = 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)")
var name: Optional<String> = Optional(nilLiteral: ())
// 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")
}
let numberToFind: Int = 23
let numberFromString: Int? = Int("23") // Optional(23)
if numberToFind == numberFromString {
    print("It's a match!") // Prints "It's a match!"
}
if nil == name { ... }
var hw = "Hello World"
//This is an error

if hw

 {..}
var nhw : String? = "Hello World"

//This is correct

if nhw

 {..}
    var aString = nil //error
    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
}
let aString: String? = "Hello, World!"
// var anotherString: String = aString //error
var anotherString: String = aString!

println(anotherString) //it will print "Hello, World!"
var middleName: String?
var middleName: String? = nil
// Here is an optional variable:

var age: Int?

// Here is how you would force unwrap it:

var unwrappedAge = age!
 if let unwrappedAge = age {

 // continue in here

 }
 guard let unwrappedAge = age else { 
   // continue in here
 }
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
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
        
    }
}
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
var personWithNoName:Person = Person.init(name: nil, company: nil)
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.
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!!!
}
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!!!
}
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
var name: String?