为什么要使用可选值?
Swift中的可选项是一种可以保存值或不保存值的类型。可选项是通过在任何类型后附加?
来编写的:
var name: String? = "Bertie"
选项(以及泛型)是最难理解的快速概念之一。由于它们是如何编写和使用的,所以很容易对它们是什么产生错误的想法。将上面的可选选项与创建普通字符串相比较:
var name: String = "Bertie" // No "?" after String
从语法上看,可选字符串与普通字符串非常相似。这不是。可选字符串不是打开了某些“可选”设置的字符串。这不是一种特殊的弦。字符串和可选字符串是完全不同的类型。
enum Optional<Wrapped> {
case none
case some(Wrapped)
}
注意:我会讲很多可选变量,但也可以创建可选常量。我用它们的类型标记所有变量,以便更容易理解正在创建的类型,但您不必在自己的代码中这样做。
若要创建可选,请在要包装的类型后追加?
。任何类型都可以是可选的,甚至是您自己的自定义类型。类型和?
之间不能有空格。
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")
}
var red: String = "Red"
red = nil // error: nil cannot be assigned to type 'String'
使用一个可选的显示了程序员的意图。与Objective-C相比,在Objective-C中,任何对象都可能为零,Swift需要您明确何时可以缺少一个值,何时可以保证该值存在。
不能使用可选的字符串
代替实际的字符串
。若要在可选项中使用包装的值,必须将其解包装。打开可选的最简单的方法是在可选名称后面添加!
。这被称为“强制展开”。它返回可选值内部的值(作为原始类型),但如果可选值为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
}
var mealPreference: String? = "Vegetarian"
if let unwrappedMealPreference: String = mealPreference {
print("Meal: \(unwrappedMealPreference)")
}
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")"
可选绑定的工作方式是检查可选值是否等于零。如果不是,它会将可选的解包装到提供的常量中,并执行该块。在Xcode 8.3和更高版本(Swift3.1)中,尝试打印类似这样的可选内容会导致一个无用的警告。使用可选的debugdescription
使其静音:
print("\(mealPreference.debugDescription)")
选项有两个用例:
let leatherTrim: CarExtras? = nil
if leatherTrim {
price = price + 1000
}
在Swift的最新版本中,您必须使用leathertrim!=nil
。这是为什么?问题是boolean
可以包装在可选的。如果您有以下boolean
:
var ambiguous: Boolean? = false
它有两种“false”,一种是没有值,另一种是有值但值是false
。Swift讨厌模棱两可,所以现在您必须始终对照nil
检查一个可选选项。
您可能想知道可选的boolean
有什么意义?与其他选项一样,.none
状态可以指示该值尚未未知。网络呼叫的另一端可能有一些东西需要一些时间来轮询。可选布尔值也称为“三值布尔值”
var religiousAffiliation: String? = "Rastafarian"
religiousAffiliation = nil
if religiousAffiliation != 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)")
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: ())
选项定义了两个特殊的“==”和“!=”运算符,您可以在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")
}
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”的名称。使用可选绑定并重用变量名来解决这一问题。
摘自Swift编程语言的“基础知识”:
Swift还引入了可选类型,用于处理没有值的情况。选项式要么说“有一个值,它等于x”,要么说“根本没有一个值”。选项类似于在Objective-C中使用nil和指针,但它们适用于任何类型,而不仅仅是类。Optionals比Objective-C中的nil指针更安全、更有表现力,是Swift许多最强大功能的核心。
选项是Swift是一种类型安全语言的一个例子。Swift帮助您明确代码可以使用的值类型。如果您的部分代码需要一个字符串,类型安全可以防止您错误地向它传递Int。这使您能够在开发过程中尽早捕获和修复错误。
最后,这里有一首1899年关于选项课的诗:
昨天在楼梯上
我遇到一个不在那里的人
他今天又不在那里
我希望,我希望他能离开
安蒂戈尼什
问题内容: 从Apple的文档中: 您可以使用和一起使用可能缺少的值。这些值表示为可选值。可选值包含一个值或包含一个指示该值丢失的值。在值的类型后写一个问号(),以将该值标记为可选。 为什么要使用可选值? 问题答案: Swift中的可选类型是可以保存值或不保存值的类型。通过将a附加到任何类型来编写可选内容: 可选(以及泛型)是最难理解的Swift概念之一。由于它们是如何编写和使用的,很容易对它们是
为什么可选在线? 当可选值包含“nil”时,必须将可选类型“Int?”的值解包为“Int”类型的值,并使用“?”合并,以提供默认值,当可选值包含“nil”时使用“!”强制解包以中止执行 所以这修复了它: 如果我将其分解,则会在添加<code>let index</code>时发生更改。。。。 OK -这将返回first的总计数,total不是可选的: 确定-此枚举和总计不是可选的: 错误 - 这会
问题内容: 如何在显示时删除可选值上的文本而不必强制输入。 更新资料 当会话具有值时,其具有值: 问题答案: 您可以使用(null合并运算符)解开它,并提供默认值(如果为nil)
问题内容: 在阅读The Swift Programming Language时 ,我遇到了以下片段: 您可以使用 if 和 let 一起使用可能缺少的值。这些值表示为 optionals 。可选值包含一个值或包含nil来指示该值丢失。在值的类型后写一个问号(?),以将该值标记为可选。 片段1很清楚,但是片段2发生了什么?有人可以分解并解释吗?它只是使用块的替代方法吗?在这种情况下的确切作用是什么
在Swift中处理选项的习惯用法似乎过于冗长,如果您只想在值为零的情况下提供一个默认值: 涉及不必要的代码复制,或者 这需要不是常量。 Scala的选项monad(与Swift的可选选项基本相同)的方法是: 我错过什么了吗?斯威夫特已经有了一个紧凑的方法来实现这一点吗?或者,如果做不到这一点,是否可以在可选的扩展中定义?
在Java8中,可以返回而不是。Java8文档说,可选的是“一个容器对象,它可以包含非空值,也可以不包含非空值。如果存在一个值,isPresent()将返回true,而get()将返回该值。” 在实践中,这为什么有用呢?另外,有没有使用作为首选项的情况?那表演呢?