The Swift Programming Language guide has the following example:
Swift编程语言指南有以下示例:
class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment?
deinit { println("\(name) is being deinitialized") }
}
class Apartment {
let number: Int
init(number: Int) { self.number = number }
var tenant: Person?
deinit { println("Apartment #\(number) is being deinitialized") }
}
var john: Person?
var number73: Apartment?
john = Person(name: "John Appleseed")
number73 = Apartment(number: 73)
//From Apple's “The Swift Programming Language” guide (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html)
Then when assigning the apartment to the person, they use an exclamation point to "unwrap the instance":
然后在分配公寓给这个人的时候,他们使用感叹号“unwrap the instance”:
john!.apartment = number73
What does it mean to "unwrap the instance"? Why is it necessary? How is it different from just doing the following:
“展开实例”是什么意思?为什么它是必要的吗?它与仅仅做以下事情有何不同?
john.apartment = number73
I'm very new to the Swift language. Just trying to get the basics down.
我对斯威夫特的语言很陌生。我只是想把基本的东西记下来。
UPDATE:
The big piece of the puzzle that I was missing (not directly stated in the answers - at least not at the time of writing this) is that when you do the following:
更新:我遗漏了一个很大的问题(答案中没有直接说明——至少在写这篇文章的时候没有),那就是当你做以下事情的时候:
var john: Person?
that does NOT mean that "john
is of type Person
and it might be nil", as I originally thought. I was simply misunderstanding that Person
and Person?
are completely separate types. Once I grasped that, all of the other ?
, !
madness, and the great answers below, made a lot more sense.
这并不意味着“john是类型Person,它可能是nil”,这是我最初的想法。我只是误解了那个人和那个人?是完全不同的类型。一旦我明白了,其他所有的?疯狂,以及下面伟大的答案,更有意义。
22 个解决方案
#1
488
What does it mean to "unwrap the instance"? Why is it necessary?
“展开实例”是什么意思?为什么它是必要的吗?
As far as I can work out (this is very new to me, too)...
就我所能做的而言(这对我来说也是全新的)……
The term "wrapped" implies we should think of an Optional variable as a present, wrapped in shiny paper, which might (sadly!) be empty.
“包装”一词意味着我们应该把一个可选的变量想象成一个礼物,用闪亮的纸包裹起来,它可能(悲哀地!)是空的。
When "wrapped", the value of an Optional variable is an enum with two possible values (a little like a Boolean). This enum describes whether the variable holds a value (Some(T)
), or not (None
).
当“包装”时,可选变量的值是一个包含两个可能值的枚举(有点像布尔值)。此枚举描述变量是否包含值(Some(T)),还是不包含(None)。
If there is a value, this can be obtained by "unwrapping" the variable (obtaining the T
from Some(T)
).
如果有一个值,可以通过“展开”变量(从某个(T)获取T)来获得。
How is
john!.apartment = number73
different fromjohn.apartment = number73
? (Paraphrased)约翰是如何!公寓和约翰不一样。公寓= number73 ?(转述)
If you write the name of an Optional variable (eg text john
, without the !
), this refers to the "wrapped" enum (Some/None), not the value itself (T). So john
isn't an instance of Person
, and it doesn't have an apartment
member:
如果你写一个可选变量的名字(例如,john,没有!),这是指“被包装的”enum(一些/没有),而不是值本身(T)。
john.apartment
// 'Person?' does not have a member named 'apartment'
The actual Person
value can be unwrapped in various ways:
实际的人的价值可以用不同的方式来包装:
- "forced unwrapping":
john!
(gives thePerson
value if it exists, runtime error if it is nil) - “强制打开”:约翰!(如果存在,则给出Person值,如果是nil,则运行时错误)
- "optional binding":
if let p = john { println(p) }
(executes theprintln
if the value exists) - “可选绑定”:如果让p = john {println(p)}(如果值存在,则执行println)
- "optional chaining":
john?.learnAboutSwift()
(executes this made-up method if the value exists) - “可选链接”:john?.learnAboutSwift()
I guess you choose one of these ways to unwrap, depending upon what should happen in the nil case, and how likely that is. This language design forces the nil case to be handled explicitly, which I suppose improves safety over Obj-C (where it is easy to forget to handle the nil case).
我猜你会选择其中一种展开方式,这取决于nil情况下会发生什么,以及这种可能性有多大。这种语言设计强制显式地处理nil用例,我认为这提高了object - c的安全性(在这里很容易忘记处理nil用例)。
Update:
更新:
The exclamation mark is also used in the syntax for declaring "Implicitly Unwrapped Optionals".
在语法中,惊叹号还用于声明“隐式展开选项”。
In the examples so far, the john
variable has been declared as var john:Person?
, and it is an Optional. If you want the actual value of that variable, you must unwrap it, using one of the three methods above.
在到目前为止的示例中,john变量被声明为var john:Person?它是可选的。如果想要该变量的实际值,必须使用上面三种方法中的一种展开它。
If it were declared as var john:Person!
instead, the variable would be an Implicitly Unwrapped Optional (see the section with this heading in Apple's book). There is no need to unwrap this kind of variable when accessing the value, and john
can be used without additional syntax. But Apple's book says:
如果它被声明为var john:Person!相反,这个变量将是一个隐式解包的可选变量(请参阅在苹果的书中带有此标题的部分)。在访问值时,不需要展开这种类型的变量,并且不需要附加语法就可以使用john。但是苹果的书说:
Implicitly unwrapped optionals should not be used when there is a possibility of a variable becoming nil at a later point. Always use a normal optional type if you need to check for a nil value during the lifetime of a variable.
当一个变量在以后可能变成nil时,不应该使用隐式展开的选项。如果需要在变量的生命周期中检查nil值,则始终使用正常的可选类型。
Update 2:
更新2:
The article "Interesting Swift Features" by Mike Ash gives some motivation for optional types. I think it is great, clear writing.
Mike Ash的文章“有趣的Swift特性”给出了一些可选类型的动机。我觉得写得很好,很清楚。
Update 3:
更新3:
Another useful article about the implicitly unwrapped optional use for the exclamation mark: "Swift and the Last Mile" by Chris Adamson. The article explains that this is a pragmatic measure by Apple used to declare the types used by their Objective-C frameworks which might contain nil. Declaring a type as optional (using ?
) or implicitly unwrapped (using !
) is "a tradeoff between safety and convenience". In the examples given in the article, Apple have chosen to declare the types as implicitly unwrapped, making the calling code more convenient, but less safe.
另一篇有用的文章是关于感叹号隐展开可选用法的:克里斯·亚当森(Chris Adamson)的《Swift和最后一英里》(Swift and the Last Mile)。本文解释说,这是苹果用来声明Objective-C框架所使用的类型的一种实用的度量,这些框架可能包含nil。声明类型为可选(使用?)或隐式打开(使用!)是“安全与方便之间的折衷”。在本文给出的示例中,苹果选择将类型声明为隐式解包,使调用代码更方便,但更不安全。
Perhaps Apple might comb through their frameworks in the future, removing the uncertainty of implicitly unwrapped ("probably never nil") parameters and replacing them with optional ("certainly could be nil in particular [hopefully, documented!] circumstances") or standard non-optional ("is never nil") declarations, based on the exact behaviour of their Objective-C code.
也许苹果将来会仔细研究它们的框架,消除隐式解包(“可能永远不会”)参数的不确定性,用可选参数替换它们(“当然可能是nil,但愿有文档!”))或标准的非可选(“从不是nil”)声明,基于它们的Objective-C代码的确切行为。
#2
115
Here is what I think is the difference:
这就是我认为的区别:
var john: Person?
Means john can be nil
意思是约翰可以是零
john?.apartment = number73
The compiler will interpret this line as:
编译器将把这一行解释为:
if john != nil {
john.apartment = number73
}
While
而
john!.apartment = number73
The compiler will interpret this line as simply:
编译器会简单地解释这一行:
john.apartment = number73
Hence, using ! will unwrap the if statement, and make it run faster, but if john is nil, then a runtime error will happen.
因此,使用!将打开if语句,并使其运行得更快,但如果john是nil,则会发生运行时错误。
So wrap here doesn't mean it is memory wrapped, but it means it is code wrapped, in this case it is wrapped with an if statement, and because Apple pay close attention to performance in runtime, they want to give you a way to make your app run with the best possible performance.
这里包装并不意味着它是记忆包,但它意味着它是代码包,在这种情况下,它是用一个if语句,因为苹果公司密切关注性能在运行时,他们想要给你一个方法让你的应用程序运行和最好的性能。
Update:
更新:
Getting back to this answer after 4 years, as I got the highest reputations from it in * :) I misunderstood a little the meaning of unwrapping at that time. Now after 4 years I believe the meaning of unwrapping here is to expand the code from its original compact form. Also it means removing the vagueness around that object, as we are not sure by definition of it is nil or not. Just like the answer of Ashley above, think about it as a present which could contain nothing in it. But I still think that the unwrapping is code unwrapping and not memory based unwrapping as using enum.
4年后回到这个问题上,因为我在*上获得了最高的声誉:)我当时有点误解了展开的意思。4年之后,我相信在这里展开的意义是将代码从原来的紧凑形式扩展出来。这也意味着要消除对象的模糊性,因为我们不确定它的定义是否为nil。就像上面艾希礼的回答一样,把它当作一件礼物,里面什么也没有。但是我仍然认为解包是代码解包,而不是像使用enum那样基于内存的解包。
#3
61
TL;DR
博士TL;
What does an exclamation mark mean in the Swift language?
在Swift语言中,惊叹号是什么意思?
The exclamation mark effectively says, “I know that this optional definitely has a value; please use it.” This is known as forced unwrapping of the optional’s value:
感叹号有效地说:“我知道这个可选项一定有值;请使用它。这被称为强制展开可选项的值:
Example
例子
let possibleString: String? = "An optional string."
print(possibleString!) // requires an exclamation mark to access its value
// prints "An optional string."
let assumedString: String! = "An implicitly unwrapped optional string."
print(assumedString) // no exclamation mark is needed to access its value
// prints "An implicitly unwrapped optional string."
来源:https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html / / apple_ref / doc / uid / TP40014097-CH5-XID_399
#4
37
If john were an optional var (declared thusly)
如果john是一个可选的var(声明如下)
var john: Person?
then it would be possible for john to have no value (in ObjC parlance, nil value)
那么约翰就有可能没有任何值(用ObjC的说法,nil值)
The exclamation point basically tells the compiler "I know this has a value, you don't need to test for it". If you didn't want to use it, you could conditionally test for it:
感叹号基本上告诉编译器“我知道它有一个值,您不需要对它进行测试”。如果您不想使用它,您可以有条件地测试它:
if let otherPerson = john {
otherPerson.apartment = number73
}
The interior of this will only evaluate if john has a value.
这个内部只有在约翰有值时才会计算。
#5
24
john
is an optional var
. So can be contains a nil
value. To ensure that the value isn't nil use a !
at the end of the var
name.
john是一个可选的var,所以be可以包含nil值。要确保值不是nil,请使用a !在var名称的末尾。
From documentation
从文档
“Once you’re sure that the optional does contain a value, you can access its underlying value by adding an exclamation mark (!) to the end of the optional’s name. The exclamation mark effectively says, “I know that this optional definitely has a value; please use it.”
一旦您确定可选项确实包含一个值,您就可以通过在可选项名称的末尾添加一个惊叹号(!)来访问它的底层值。感叹号有效地说:“我知道这个可选项一定有值;请使用它。”
Another way to check non nil value is
另一种检查非nil值的方法是
if let j = json {
// do something with j
}
#6
24
Some big picture perspective to add to the other useful but more detail-centric answers:
一些大的图片视角可以增加其他有用但更详细的答案:
In Swift, the exclamation point appears in several contexts:
在Swift中,感叹号出现在几个上下文中:
- Forced unwrapping:
let name = nameLabel!.text
- 强制打开:让name = nameLabel!.text。
- Implicitly unwrapped optionals:
var logo: UIImageView!
- 隐式展开选项:var logo: UIImageView!
- Forced casting:
logo.image = thing as! UIImage
- 迫使铸造:标志。形象=东西!用户界面图像
- Unhandled exceptions:
try! NSJSONSerialization.JSONObjectWithData(data, [])
- 未处理的异常:试试!NSJSONSerialization。JSONObjectWithData(数据,[])
Every one of these is a different language construct with a different meaning, but they all have three important things in common:
每一个都是不同的语言结构,有着不同的含义,但它们都有三个重要的共同点:
1. Exclamation points circumvent Swift’s compile-time safety checks.
When you use !
in Swift, you are essentially saying, “Hey, compiler, I know you think an error could happen here, but I know with total certainty that it never will.”
当你使用!在Swift中,您实际上是在说,“嘿,编译器,我知道您认为这里可能会发生错误,但我完全肯定它永远不会发生。”
Not all valid code fits into the box of Swift’s compile-time type system — or any language’s static type checking, for that matter. There are situations where you can logically prove that an error will never happen, but you can’t prove it to the compiler. That’s why Swift’s designers added these features in the first place.
并不是所有的有效代码都适合Swift的编译时类型系统——或者任何语言的静态类型检查。在某些情况下,您可以逻辑地证明一个错误永远不会发生,但是您不能向编译器证明它。这就是为什么斯威夫特的设计师们首先添加了这些功能。
However, whenever you use !
, you’re ruling out having a recovery path for an error, which means that…
然而,无论何时使用!,您都排除了为错误设置恢复路径的可能性,这意味着……
2. Exclamation points are potential crashes.
An exclamation point also says, “Hey Swift, I am so certain that this error can never happen that it’s better for you to crash my whole app than it is for me to code a recovery path for it.”
一个感叹号还说,“嘿,斯威夫特,我很确定这个错误永远不会发生,我的整个应用程序崩溃了,比我为它编码恢复路径要好得多。”
That’s a dangerous assertion. It can be the correct one: in mission-critical code where you have thought hard about your code’s invariants, it may be that bogus output is worse than a crash.
这是一个危险的主张。它可能是正确的:在任务关键型代码中,如果您认真考虑过代码的不变量,那么伪输出可能比崩溃更糟糕。
However, when I see !
in the wild, it's rarely used so mindfully. Instead, it too often means, “this value was optional and I didn’t really think too hard about why it could be nil or how to properly handle that situation, but adding !
made it compile … so my code is correct, right?”
然而,当我看到!在野外,它很少被如此用心地使用。相反,它往往意味着,“这个值是可选的,我并没有认真考虑为什么它可以是nil,或者如何正确地处理这种情况,而是添加!”我的代码是正确的,对吧?
Beware the arrogance of the exclamation point. Instead…
注意感叹号的傲慢。而不是……
3. Exclamation points are best used sparingly.
Every one of these !
constructs has a ?
counterpart that forces you to deal with the error/nil case:
每一个!构造有一个吗?迫使您处理错误/nil情况的对应关系:
- Conditional unwrapping:
if let name = nameLabel?.text { ... }
- 条件展开:如果让name = nameLabel?文本{…}
- Optionals:
var logo: UIImageView?
- 可选:var标志:UIImageView ?
- Conditional casts:
logo.image = thing as? UIImage
- 条件投:标志。形象=东西?用户界面图像
- Nil-on-failure exceptions:
try? NSJSONSerialization.JSONObjectWithData(data, [])
- Nil-on-failure例外:试试?NSJSONSerialization。JSONObjectWithData(数据,[])
If you are tempted to use !
, it is always good to consider carefully why you are not using ?
instead. Is crashing your program really the best option if the !
operation fails? Why is that value optional/failable?
如果你被诱惑使用!,仔细考虑为什么不使用总是好的。代替。崩溃你的程序真的是最好的选择如果!操作失败?为什么这个值是可选/可失败的?
Is there a reasonable recovery path your code could take in the nil/error case? If so, code it.
是否有一个合理的恢复路径,您的代码可以采用nil/error的情况?如果是这样,它的代码。
If it can’t possibly be nil, if the error can never happen, then is there a reasonable way to rework your logic so that the compiler knows that? If so, do it; your code will be less error-prone.
如果它不可能是nil,如果错误永远不会发生,那么是否有一种合理的方法来重写逻辑,让编译器知道这一点?如果是这样,做;您的代码将更不容易出错。
There are times when there is no reasonable way to handle an error, and simply ignoring the error — and thus proceeding with wrong data — would be worse than crashing. Those are the times to use force unwrapping.
有时,没有合理的方法来处理错误,而仅仅忽略错误——从而处理错误的数据——将比崩溃更糟糕。这是使用武力展开的时代。
I periodically search my entire codebase for !
and audit every use of it. Very few usages stand up to scrutiny. (As of this writing, the entire Siesta framework has exactly two instances of it.)
我定期搜索我的整个代码基!并对它的使用进行审核。很少有惯例经得起推敲。(在撰写本文时,整个午睡框架恰好有两个实例。)
That’s not to say you should never use !
in your code — just that you should use it mindfully, and never make it the default option.
这并不是说你不应该使用!在您的代码中—只是您应该谨慎地使用它,并且永远不要将它作为默认选项。
#7
16
Here are some examples:
下面是一些例子:
var name:String = "Hello World"
var word:String?
Where word
is an optional value. means it may or may not contain a value.
其中word是可选值。意味着它可能包含也可能不包含值。
word = name
Here name
has a value so we can assign it
这里的名称有一个值,所以我们可以分配它
var cow:String = nil
var dog:String!
Where dog
is forcefully unwrapped means it must contain a value
狗被强行打开意味着它必须包含一个值
dog = cow
The application will crash because we are assign nil
to unwrapped
应用程序将崩溃,因为我们将nil分配给unwrap
#8
13
In this case...
在这种情况下……
var John: Person!
var约翰:人!
it means, that initially John will have nil value, it will be set and once set will never be nil-led again. Therefore for convenience I can use the easier syntax for accessing an optional var because this is an "Implicitly unwrapped optional"
它的意思是,约翰一开始会有nil值,它会被设置,一旦被设置,它就再也不会是nilled了。因此,为了方便起见,我可以使用更简单的语法来访问可选的var,因为这是一个“隐式未封装可选的”
#9
4
If you've come from a C-family language, you will be thinking "pointer to object of type X which might be the memory address 0 (NULL)", and if you're coming from a dynamically typed language you'll be thinking "Object which is probably of type X but might be of type undefined". Neither of these is actually correct, although in a roundabout way the first one is close.
如果您来自c族语言,您将会想到“指向X类型的对象,它可能是内存地址0 (NULL)”。,如果你来自一个动态类型语言,你会想“对象可能是类型为X的,但类型可能是未定义的”。这两种说法实际上都不对,尽管第一种说法有点拐弯抹角。
The way you should be thinking of it is as if it's an object like:
你应该这样想它就好像它是一个物体
struct Optional<T> {
var isNil:Boolean
var realObject:T
}
When you're testing your optional value with foo == nil
it's really returning foo.isNil
, and when you say foo!
it's returning foo.realObject
with an assertion that foo.isNil == false
. It's important to note this because if foo
actually is nil when you do foo!
, that's a runtime error, so typically you'd want to use a conditional let instead unless you are very sure that the value will not be nil. This kind of trickery means that the language can be strongly typed without forcing you to test if values are nil everywhere.
当你用foo = nil测试你的可选值时它实际上是在返回foo。isNil,当你说foo!这是返回foo。具有foo的断言的realObject。isNil = = false。注意这一点很重要,因为如果foo实际上是nil,那么foo!,这是一个运行时错误,所以通常您需要使用条件let,除非您非常确定该值不是nil。这种欺骗意味着语言可以被强类型输入,而不需要测试值是否为nil。
In practice, it doesn't truly behave like that because the work is done by the compiler. At a high level there is a type Foo?
which is separate to Foo
, and that prevents funcs which accept type Foo
from receiving a nil value, but at a low level an optional value isn't a true object because it has no properties or methods; it's likely that in fact it is a pointer which may by NULL(0) with the appropriate test when force-unwrapping.
实际上,它并不是那样的,因为工作是由编译器完成的。在高水平上有一个类型Foo?它是独立于Foo的,这阻止了接受Foo类型的函数接收nil值,但在较低的层次上,可选值不是真正的对象,因为它没有属性或方法;实际上,它很可能是一个指针,在强制展开时,它的值可能为NULL(0),并带有适当的测试。
There other situation in which you'd see an exclamation mark is on a type, as in:
在其他情况下,你会看到一个感叹号在一个类型上,如:
func foo(bar: String!) {
print(bar)
}
This is roughly equivalent to accepting an optional with a forced unwrap, i.e.:
这大致相当于接受带有强制展开的可选选项,即:
func foo(bar: String?) {
print(bar!)
}
You can use this to have a method which technically accepts an optional value but will have a runtime error if it is nil. In the current version of Swift this apparently bypasses the is-not-nil assertion so you'll have a low-level error instead. Generally not a good idea, but it can be useful when converting code from another language.
您可以使用它来拥有一个方法,该方法技术上接受一个可选值,但如果它是nil,则会有一个运行时错误。在当前版本的Swift中,这显然绕过了is-not-nil断言,因此您将得到一个低级错误。一般来说,这不是一个好主意,但是当从另一种语言转换代码时,它是有用的。
#10
3
The ! means that you are force unwrapping the object the ! follows. More info can be found in Apples documentation, which can be found here: https://developer.apple.com/library/ios/documentation/swift/conceptual/Swift_Programming_Language/TheBasics.html
!意思是你正在用力把物体打开!遵循。更多信息可以在苹果文档中找到,可以在这里找到:https://developer.apple.com/library/ios/documentation/swift/conceptual/swift_programming_language/basics.html
#11
3
If you're familiar with C#, this is like Nullable types which are also declared using a question mark:
如果您熟悉c#,这类似于可以空的类型,也使用问号声明:
Person? thisPerson;
And the exclamation mark in this case is equivalent to accessing the .Value property of the nullable type like this:
在本例中,感叹号等同于访问可空类型的.Value属性,如下所示:
thisPerson.Value
#12
2
In objective C variables with no value were equal to 'nil'(it was also possible to use 'nil' values same as 0 and false), hence it was possible to use variables in conditional statements (Variables having values are same as 'TRUE' and those with no values were equal to 'FALSE').
在objective C中,没有值的变量等于nil(也可以使用0和false的nil值),因此也可以在条件语句中使用变量(值为TRUE的变量和值为false的变量)。
Swift provides type safety by providing 'optional value'. i.e. It prevents errors formed from assigning variables of different types.
Swift通过提供“可选值”提供类型安全。也就是说,它可以防止由于分配不同类型的变量而产生的错误。
So in Swift, only booleans can be provided on conditional statements.
因此,在Swift中,只能在条件语句中提供布尔值。
var hw = "Hello World"
Here, even-though 'hw' is a string, it can't be used in an if statement like in objective C.
在这里,即使“hw”是一个字符串,也不能在objective C中的if语句中使用。
//This is an error
if hw
{..}
For that it needs to be created as,
为此,它需要创建为,
var nhw : String? = "Hello World"
//This is correct
if nhw
{..}
#13
2
The ! at the end of an object says the object is an optional and to unwrap if it can otherwise returns a nil. This is often used to trap errors that would otherwise crash the program.
!在对象的末尾,表示对象是可选的,如果它可以返回nil,则打开该对象。这通常用于捕捉错误,否则会导致程序崩溃。
#14
2
In Short (!): After you have declare a variable and that you are certain the variable is holding a value.
简而言之(!):在声明一个变量并确定该变量持有一个值之后。
let assumedString: String! = "Some message..."
let implicitString: String = assumedString
else you would have to do this on every after passing value...
否则,在传递值之后,您将不得不对每个对象执行此操作……
let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // requires an exclamation mark
#15
1
John is an optional Person, meaning it can hold a value or be nil.
John是一个可选的人,这意味着它可以持有一个值或为nil。
john.apartment = number73
is used if john is not an optional. Since john is never nil we can be sure it won't call apartment on a nil value. While
如果john不是可选的,则使用。因为约翰从来都不是nil,我们可以确定它不会以nil值调用公寓。而
john!.apartment = number73
promises the compiler that john is not nil then unwraps the optional to get john's value and accesses john's apartment property. Use this if you know that john is not nil. If you call this on a nil optional, you'll get a runtime error.
向编译器保证john不是nil,然后打开可选项获取john的值并访问john的公寓属性。如果你知道约翰不是nil,就用这个。如果你在一个空选项中调用这个,你会得到一个运行时错误。
The documentation includes a nice example for using this where convertedNumber is an optional.
文档中有一个很好的例子,可以使用convertedNumber是可选的。
if convertedNumber {
println("\(possibleNumber) has an integer value of \(convertedNumber!)")
} else {
println("\(possibleNumber) could not be converted to an integer")
}
#16
1
To put it simply, exclamation marks mean an optional is being unwrapped. An optional is a variable that can have a value or not -- so you can check if the variable is empty, using an if let statement as shown here, and then force unwrap it. If you force unwrap an optional that is empty though, your program will crash, so be careful! Optionals are declared by putting a question mark at the end of an explicit assignment to a variable, for example I could write:
简单地说,感叹号意味着一个可选项正在展开。可选是一个变量,它可以有值也可以没有值——所以您可以使用if let语句检查变量是否为空,然后强制展开它。如果您强制打开一个可选的空包装,您的程序将崩溃,所以要小心!选项是通过在变量的显式赋值的末尾加一个问号来声明的,例如,我可以这样写:
var optionalExample: String?
This variable has no value. If I were to unwrap it, the program would crash and Xcode would tell you you tried to unwrap an optional with a value of nil.
这个变量没有值。如果我打开它,程序会崩溃,Xcode会告诉你你试图打开一个可选的,值为nil。
Hope that helped.
希望帮助。
#17
1
IN SIMPLE WORDS
用简单的单词
USING Exclamation mark indicates that variable must consists non nil value (it never be nil)
使用感叹号表示变量必须包含非nil值(它从不是nil)
#18
1
The entire story begins with a feature of swift called optional vars. These are the vars which may have a value or may not have a value. In general swift doesn't allow us to use a variable which isn't initialised, as this may lead to crashes or unexpected reasons and also server a placeholder for backdoors. Thus in order to declare a variable whose value isn't initially determined we use a '?'. When such a variable is declared, to use it as a part of some expression one has to unwrap them before use, unwrapping is an operation through which value of a variable is discovered this applies to objects. Without unwrapping if you try to use them you will have compile time error. To unwrap a variable which is an optional var, exclamation mark "!" is used.
整个故事以斯威夫特的一个特点开始,叫做可选vars。这些vars可能有价值,也可能没有价值。一般来说,swift不允许我们使用未初始化的变量,因为这可能导致崩溃或意想不到的原因,并且服务器是后门的占位符。因此,为了声明一个最初未确定值的变量,我们使用'?'。当声明这样一个变量时,要将其作为某个表达式的一部分,必须在使用之前展开它们,展开是一个操作,通过这个操作可以发现一个变量的值,并将其应用于对象。如果您试图使用它们,没有展开包装,您将会有编译时错误。要打开可选的变量var,使用感叹号“!”。
Now there are times when you know that such optional variables will be assigned values by system for example or your own program but sometime later , for example UI outlets, in such situation instead of declaring an optional variable using a question mark "?" we use "!".
现在有些时候,你知道这些可选的变量将被系统分配给你自己的程序,或者你自己的程序,但是在以后的某个时候,比如UI,在这样的情况下,而不是用问号来声明一个可选的变量,我们用“!”
Thus system knows that this variable which is declared with "!" is optional right now and has no value but will receive a value in later in its lifetime.
因此系统知道这个用“!”声明的变量现在是可选的,并且没有任何值,但是在以后的生命中会收到一个值。
Thus exclamation mark holds two different usages, 1. To declare a variable which will be optional and will receive value definitely later 2. To unwrap an optional variable before using it in an expression.
因此,感叹号有两个不同的用法:1。要声明一个变量,该变量将是可选的,并且在以后一定会收到值2。在表达式中使用可选变量之前展开可选变量。
Above descriptions avoids too much of technical stuff, i hope.
我希望上面的描述避免了太多的技术性的东西。
#19
1
If you use it as an optional, it unwraps the optional and sees if something is there. If you use it in an if-else statement is is code for NOT. For example,
如果您将它用作可选项,它将打开可选项,并查看是否存在某些内容。如果在If -else语句中使用它,则是不使用代码。例如,
if (myNumber != 3){
// if myNumber is NOT 3 do whatever is inside these brackets.
)
#20
1
An Optional variable may contain a value or may be not
可选的变量可能包含一个值,也可能不是。
case 1: var myVar:String? = "Something"
案例1:var myvar#:字符串?= "东西"
case 2: var myVar:String? = nil
案例2:var myvar#:字符串?= nil
now if you ask myVar!, you are telling compiler to return a value in case 1 it will return "Something"
如果你问myVar!,你告诉编译器返回一个值,在情况1中它会返回“某物”
in case 2 it will crash.
在第二种情况下它会崩溃。
Meaning ! mark will force compiler to return a value, even if its not there. thats why the name Force Unwrapping.
的意思!mark将强制编译器返回一个值,即使它不在那里。这就是为什么“力量”这个名字被拆开的原因。
#21
0
Simple the Optional variable allows nil to be stored.
var str : String? = nil
str = "Data"
To convert Optional to the Specific DataType, We unwrap the variable using the keyword "!"
func get(message : String){
return
}
get(message : str!) // Unwapped to pass as String
#22
-1
ASK YOURSELF
问问你自己
- Does the type
person?
have anapartment
member/property? OR - 类型的人吗?有一个公寓成员/财产吗?或
- Does the type
person
have anapartment
member/property? - 类型的人有公寓成员/财产吗?
If you can't answer this question, then continue reading:
如果你不能回答这个问题,继续阅读:
To understand you may need super-basic level of understanding of Generics. See here. A lot of things in Swift are written using Generics. Optionals included
要理解泛型,您可能需要非常基本的泛型理解。在这里看到的。Swift中的许多内容都是使用泛型编写的。可选的包括
The code below has been made available from this Stanford video. Highly recommend you to watch the first 5 minutes
下面的代码可以从斯坦福大学的这段视频中找到。强烈建议你看前5分钟
An Optional is an enum with only 2 cases
enum Optional<T>{
case None
case Some(T)
}
let x: String? = nil //actually means:
let x = Optional<String>.None
let x :String? = "hello" //actually means:
let x = Optional<String>.Some("hello")
var y = x! // actually means:
switch x {
case .Some(let value): y = value
case .None: // Raise an exception
}
Optional binding:
let x:String? = something
if let y = x {
// do something with y
}
//Actually means:
switch x{
case .Some(let y): print)(y) // or whatever else you like using
case .None: break
}
when you say var john: Person?
You actually mean such:
你说var john: Person?你的意思是这样的:
enum Optional<Person>{
case .None
case .Some(Person)
}
Does the above enum have any property named apartment
? Do you see it anywhere? It's not there at all! However if you unwrap it ie do person!
then you can ... what it does under the hood is : Optional<Person>.Some(Person(name: "John Appleseed"))
上述全会是否有任何财产命名公寓?你在哪儿见过它吗?根本不存在!但是如果你打开它(做人)!然后你可以…它的作用是:可选的
Had you defined var john: Person
instead of: var john: Person?
then you would have no longer needed to have the !
used, because Person
itself does have a member of apartment
你定义了var john: Person而不是var john: Person吗?那么你就不再需要拥有!使用,因为人本身就有一个公寓成员
As a future discussion on why using !
to unwrap is sometimes not recommended see this Q&A
作为未来讨论为什么使用!有时不建议打开这个问题
#1
488
What does it mean to "unwrap the instance"? Why is it necessary?
“展开实例”是什么意思?为什么它是必要的吗?
As far as I can work out (this is very new to me, too)...
就我所能做的而言(这对我来说也是全新的)……
The term "wrapped" implies we should think of an Optional variable as a present, wrapped in shiny paper, which might (sadly!) be empty.
“包装”一词意味着我们应该把一个可选的变量想象成一个礼物,用闪亮的纸包裹起来,它可能(悲哀地!)是空的。
When "wrapped", the value of an Optional variable is an enum with two possible values (a little like a Boolean). This enum describes whether the variable holds a value (Some(T)
), or not (None
).
当“包装”时,可选变量的值是一个包含两个可能值的枚举(有点像布尔值)。此枚举描述变量是否包含值(Some(T)),还是不包含(None)。
If there is a value, this can be obtained by "unwrapping" the variable (obtaining the T
from Some(T)
).
如果有一个值,可以通过“展开”变量(从某个(T)获取T)来获得。
How is
john!.apartment = number73
different fromjohn.apartment = number73
? (Paraphrased)约翰是如何!公寓和约翰不一样。公寓= number73 ?(转述)
If you write the name of an Optional variable (eg text john
, without the !
), this refers to the "wrapped" enum (Some/None), not the value itself (T). So john
isn't an instance of Person
, and it doesn't have an apartment
member:
如果你写一个可选变量的名字(例如,john,没有!),这是指“被包装的”enum(一些/没有),而不是值本身(T)。
john.apartment
// 'Person?' does not have a member named 'apartment'
The actual Person
value can be unwrapped in various ways:
实际的人的价值可以用不同的方式来包装:
- "forced unwrapping":
john!
(gives thePerson
value if it exists, runtime error if it is nil) - “强制打开”:约翰!(如果存在,则给出Person值,如果是nil,则运行时错误)
- "optional binding":
if let p = john { println(p) }
(executes theprintln
if the value exists) - “可选绑定”:如果让p = john {println(p)}(如果值存在,则执行println)
- "optional chaining":
john?.learnAboutSwift()
(executes this made-up method if the value exists) - “可选链接”:john?.learnAboutSwift()
I guess you choose one of these ways to unwrap, depending upon what should happen in the nil case, and how likely that is. This language design forces the nil case to be handled explicitly, which I suppose improves safety over Obj-C (where it is easy to forget to handle the nil case).
我猜你会选择其中一种展开方式,这取决于nil情况下会发生什么,以及这种可能性有多大。这种语言设计强制显式地处理nil用例,我认为这提高了object - c的安全性(在这里很容易忘记处理nil用例)。
Update:
更新:
The exclamation mark is also used in the syntax for declaring "Implicitly Unwrapped Optionals".
在语法中,惊叹号还用于声明“隐式展开选项”。
In the examples so far, the john
variable has been declared as var john:Person?
, and it is an Optional. If you want the actual value of that variable, you must unwrap it, using one of the three methods above.
在到目前为止的示例中,john变量被声明为var john:Person?它是可选的。如果想要该变量的实际值,必须使用上面三种方法中的一种展开它。
If it were declared as var john:Person!
instead, the variable would be an Implicitly Unwrapped Optional (see the section with this heading in Apple's book). There is no need to unwrap this kind of variable when accessing the value, and john
can be used without additional syntax. But Apple's book says:
如果它被声明为var john:Person!相反,这个变量将是一个隐式解包的可选变量(请参阅在苹果的书中带有此标题的部分)。在访问值时,不需要展开这种类型的变量,并且不需要附加语法就可以使用john。但是苹果的书说:
Implicitly unwrapped optionals should not be used when there is a possibility of a variable becoming nil at a later point. Always use a normal optional type if you need to check for a nil value during the lifetime of a variable.
当一个变量在以后可能变成nil时,不应该使用隐式展开的选项。如果需要在变量的生命周期中检查nil值,则始终使用正常的可选类型。
Update 2:
更新2:
The article "Interesting Swift Features" by Mike Ash gives some motivation for optional types. I think it is great, clear writing.
Mike Ash的文章“有趣的Swift特性”给出了一些可选类型的动机。我觉得写得很好,很清楚。
Update 3:
更新3:
Another useful article about the implicitly unwrapped optional use for the exclamation mark: "Swift and the Last Mile" by Chris Adamson. The article explains that this is a pragmatic measure by Apple used to declare the types used by their Objective-C frameworks which might contain nil. Declaring a type as optional (using ?
) or implicitly unwrapped (using !
) is "a tradeoff between safety and convenience". In the examples given in the article, Apple have chosen to declare the types as implicitly unwrapped, making the calling code more convenient, but less safe.
另一篇有用的文章是关于感叹号隐展开可选用法的:克里斯·亚当森(Chris Adamson)的《Swift和最后一英里》(Swift and the Last Mile)。本文解释说,这是苹果用来声明Objective-C框架所使用的类型的一种实用的度量,这些框架可能包含nil。声明类型为可选(使用?)或隐式打开(使用!)是“安全与方便之间的折衷”。在本文给出的示例中,苹果选择将类型声明为隐式解包,使调用代码更方便,但更不安全。
Perhaps Apple might comb through their frameworks in the future, removing the uncertainty of implicitly unwrapped ("probably never nil") parameters and replacing them with optional ("certainly could be nil in particular [hopefully, documented!] circumstances") or standard non-optional ("is never nil") declarations, based on the exact behaviour of their Objective-C code.
也许苹果将来会仔细研究它们的框架,消除隐式解包(“可能永远不会”)参数的不确定性,用可选参数替换它们(“当然可能是nil,但愿有文档!”))或标准的非可选(“从不是nil”)声明,基于它们的Objective-C代码的确切行为。
#2
115
Here is what I think is the difference:
这就是我认为的区别:
var john: Person?
Means john can be nil
意思是约翰可以是零
john?.apartment = number73
The compiler will interpret this line as:
编译器将把这一行解释为:
if john != nil {
john.apartment = number73
}
While
而
john!.apartment = number73
The compiler will interpret this line as simply:
编译器会简单地解释这一行:
john.apartment = number73
Hence, using ! will unwrap the if statement, and make it run faster, but if john is nil, then a runtime error will happen.
因此,使用!将打开if语句,并使其运行得更快,但如果john是nil,则会发生运行时错误。
So wrap here doesn't mean it is memory wrapped, but it means it is code wrapped, in this case it is wrapped with an if statement, and because Apple pay close attention to performance in runtime, they want to give you a way to make your app run with the best possible performance.
这里包装并不意味着它是记忆包,但它意味着它是代码包,在这种情况下,它是用一个if语句,因为苹果公司密切关注性能在运行时,他们想要给你一个方法让你的应用程序运行和最好的性能。
Update:
更新:
Getting back to this answer after 4 years, as I got the highest reputations from it in * :) I misunderstood a little the meaning of unwrapping at that time. Now after 4 years I believe the meaning of unwrapping here is to expand the code from its original compact form. Also it means removing the vagueness around that object, as we are not sure by definition of it is nil or not. Just like the answer of Ashley above, think about it as a present which could contain nothing in it. But I still think that the unwrapping is code unwrapping and not memory based unwrapping as using enum.
4年后回到这个问题上,因为我在*上获得了最高的声誉:)我当时有点误解了展开的意思。4年之后,我相信在这里展开的意义是将代码从原来的紧凑形式扩展出来。这也意味着要消除对象的模糊性,因为我们不确定它的定义是否为nil。就像上面艾希礼的回答一样,把它当作一件礼物,里面什么也没有。但是我仍然认为解包是代码解包,而不是像使用enum那样基于内存的解包。
#3
61
TL;DR
博士TL;
What does an exclamation mark mean in the Swift language?
在Swift语言中,惊叹号是什么意思?
The exclamation mark effectively says, “I know that this optional definitely has a value; please use it.” This is known as forced unwrapping of the optional’s value:
感叹号有效地说:“我知道这个可选项一定有值;请使用它。这被称为强制展开可选项的值:
Example
例子
let possibleString: String? = "An optional string."
print(possibleString!) // requires an exclamation mark to access its value
// prints "An optional string."
let assumedString: String! = "An implicitly unwrapped optional string."
print(assumedString) // no exclamation mark is needed to access its value
// prints "An implicitly unwrapped optional string."
来源:https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html / / apple_ref / doc / uid / TP40014097-CH5-XID_399
#4
37
If john were an optional var (declared thusly)
如果john是一个可选的var(声明如下)
var john: Person?
then it would be possible for john to have no value (in ObjC parlance, nil value)
那么约翰就有可能没有任何值(用ObjC的说法,nil值)
The exclamation point basically tells the compiler "I know this has a value, you don't need to test for it". If you didn't want to use it, you could conditionally test for it:
感叹号基本上告诉编译器“我知道它有一个值,您不需要对它进行测试”。如果您不想使用它,您可以有条件地测试它:
if let otherPerson = john {
otherPerson.apartment = number73
}
The interior of this will only evaluate if john has a value.
这个内部只有在约翰有值时才会计算。
#5
24
john
is an optional var
. So can be contains a nil
value. To ensure that the value isn't nil use a !
at the end of the var
name.
john是一个可选的var,所以be可以包含nil值。要确保值不是nil,请使用a !在var名称的末尾。
From documentation
从文档
“Once you’re sure that the optional does contain a value, you can access its underlying value by adding an exclamation mark (!) to the end of the optional’s name. The exclamation mark effectively says, “I know that this optional definitely has a value; please use it.”
一旦您确定可选项确实包含一个值,您就可以通过在可选项名称的末尾添加一个惊叹号(!)来访问它的底层值。感叹号有效地说:“我知道这个可选项一定有值;请使用它。”
Another way to check non nil value is
另一种检查非nil值的方法是
if let j = json {
// do something with j
}
#6
24
Some big picture perspective to add to the other useful but more detail-centric answers:
一些大的图片视角可以增加其他有用但更详细的答案:
In Swift, the exclamation point appears in several contexts:
在Swift中,感叹号出现在几个上下文中:
- Forced unwrapping:
let name = nameLabel!.text
- 强制打开:让name = nameLabel!.text。
- Implicitly unwrapped optionals:
var logo: UIImageView!
- 隐式展开选项:var logo: UIImageView!
- Forced casting:
logo.image = thing as! UIImage
- 迫使铸造:标志。形象=东西!用户界面图像
- Unhandled exceptions:
try! NSJSONSerialization.JSONObjectWithData(data, [])
- 未处理的异常:试试!NSJSONSerialization。JSONObjectWithData(数据,[])
Every one of these is a different language construct with a different meaning, but they all have three important things in common:
每一个都是不同的语言结构,有着不同的含义,但它们都有三个重要的共同点:
1. Exclamation points circumvent Swift’s compile-time safety checks.
When you use !
in Swift, you are essentially saying, “Hey, compiler, I know you think an error could happen here, but I know with total certainty that it never will.”
当你使用!在Swift中,您实际上是在说,“嘿,编译器,我知道您认为这里可能会发生错误,但我完全肯定它永远不会发生。”
Not all valid code fits into the box of Swift’s compile-time type system — or any language’s static type checking, for that matter. There are situations where you can logically prove that an error will never happen, but you can’t prove it to the compiler. That’s why Swift’s designers added these features in the first place.
并不是所有的有效代码都适合Swift的编译时类型系统——或者任何语言的静态类型检查。在某些情况下,您可以逻辑地证明一个错误永远不会发生,但是您不能向编译器证明它。这就是为什么斯威夫特的设计师们首先添加了这些功能。
However, whenever you use !
, you’re ruling out having a recovery path for an error, which means that…
然而,无论何时使用!,您都排除了为错误设置恢复路径的可能性,这意味着……
2. Exclamation points are potential crashes.
An exclamation point also says, “Hey Swift, I am so certain that this error can never happen that it’s better for you to crash my whole app than it is for me to code a recovery path for it.”
一个感叹号还说,“嘿,斯威夫特,我很确定这个错误永远不会发生,我的整个应用程序崩溃了,比我为它编码恢复路径要好得多。”
That’s a dangerous assertion. It can be the correct one: in mission-critical code where you have thought hard about your code’s invariants, it may be that bogus output is worse than a crash.
这是一个危险的主张。它可能是正确的:在任务关键型代码中,如果您认真考虑过代码的不变量,那么伪输出可能比崩溃更糟糕。
However, when I see !
in the wild, it's rarely used so mindfully. Instead, it too often means, “this value was optional and I didn’t really think too hard about why it could be nil or how to properly handle that situation, but adding !
made it compile … so my code is correct, right?”
然而,当我看到!在野外,它很少被如此用心地使用。相反,它往往意味着,“这个值是可选的,我并没有认真考虑为什么它可以是nil,或者如何正确地处理这种情况,而是添加!”我的代码是正确的,对吧?
Beware the arrogance of the exclamation point. Instead…
注意感叹号的傲慢。而不是……
3. Exclamation points are best used sparingly.
Every one of these !
constructs has a ?
counterpart that forces you to deal with the error/nil case:
每一个!构造有一个吗?迫使您处理错误/nil情况的对应关系:
- Conditional unwrapping:
if let name = nameLabel?.text { ... }
- 条件展开:如果让name = nameLabel?文本{…}
- Optionals:
var logo: UIImageView?
- 可选:var标志:UIImageView ?
- Conditional casts:
logo.image = thing as? UIImage
- 条件投:标志。形象=东西?用户界面图像
- Nil-on-failure exceptions:
try? NSJSONSerialization.JSONObjectWithData(data, [])
- Nil-on-failure例外:试试?NSJSONSerialization。JSONObjectWithData(数据,[])
If you are tempted to use !
, it is always good to consider carefully why you are not using ?
instead. Is crashing your program really the best option if the !
operation fails? Why is that value optional/failable?
如果你被诱惑使用!,仔细考虑为什么不使用总是好的。代替。崩溃你的程序真的是最好的选择如果!操作失败?为什么这个值是可选/可失败的?
Is there a reasonable recovery path your code could take in the nil/error case? If so, code it.
是否有一个合理的恢复路径,您的代码可以采用nil/error的情况?如果是这样,它的代码。
If it can’t possibly be nil, if the error can never happen, then is there a reasonable way to rework your logic so that the compiler knows that? If so, do it; your code will be less error-prone.
如果它不可能是nil,如果错误永远不会发生,那么是否有一种合理的方法来重写逻辑,让编译器知道这一点?如果是这样,做;您的代码将更不容易出错。
There are times when there is no reasonable way to handle an error, and simply ignoring the error — and thus proceeding with wrong data — would be worse than crashing. Those are the times to use force unwrapping.
有时,没有合理的方法来处理错误,而仅仅忽略错误——从而处理错误的数据——将比崩溃更糟糕。这是使用武力展开的时代。
I periodically search my entire codebase for !
and audit every use of it. Very few usages stand up to scrutiny. (As of this writing, the entire Siesta framework has exactly two instances of it.)
我定期搜索我的整个代码基!并对它的使用进行审核。很少有惯例经得起推敲。(在撰写本文时,整个午睡框架恰好有两个实例。)
That’s not to say you should never use !
in your code — just that you should use it mindfully, and never make it the default option.
这并不是说你不应该使用!在您的代码中—只是您应该谨慎地使用它,并且永远不要将它作为默认选项。
#7
16
Here are some examples:
下面是一些例子:
var name:String = "Hello World"
var word:String?
Where word
is an optional value. means it may or may not contain a value.
其中word是可选值。意味着它可能包含也可能不包含值。
word = name
Here name
has a value so we can assign it
这里的名称有一个值,所以我们可以分配它
var cow:String = nil
var dog:String!
Where dog
is forcefully unwrapped means it must contain a value
狗被强行打开意味着它必须包含一个值
dog = cow
The application will crash because we are assign nil
to unwrapped
应用程序将崩溃,因为我们将nil分配给unwrap
#8
13
In this case...
在这种情况下……
var John: Person!
var约翰:人!
it means, that initially John will have nil value, it will be set and once set will never be nil-led again. Therefore for convenience I can use the easier syntax for accessing an optional var because this is an "Implicitly unwrapped optional"
它的意思是,约翰一开始会有nil值,它会被设置,一旦被设置,它就再也不会是nilled了。因此,为了方便起见,我可以使用更简单的语法来访问可选的var,因为这是一个“隐式未封装可选的”
#9
4
If you've come from a C-family language, you will be thinking "pointer to object of type X which might be the memory address 0 (NULL)", and if you're coming from a dynamically typed language you'll be thinking "Object which is probably of type X but might be of type undefined". Neither of these is actually correct, although in a roundabout way the first one is close.
如果您来自c族语言,您将会想到“指向X类型的对象,它可能是内存地址0 (NULL)”。,如果你来自一个动态类型语言,你会想“对象可能是类型为X的,但类型可能是未定义的”。这两种说法实际上都不对,尽管第一种说法有点拐弯抹角。
The way you should be thinking of it is as if it's an object like:
你应该这样想它就好像它是一个物体
struct Optional<T> {
var isNil:Boolean
var realObject:T
}
When you're testing your optional value with foo == nil
it's really returning foo.isNil
, and when you say foo!
it's returning foo.realObject
with an assertion that foo.isNil == false
. It's important to note this because if foo
actually is nil when you do foo!
, that's a runtime error, so typically you'd want to use a conditional let instead unless you are very sure that the value will not be nil. This kind of trickery means that the language can be strongly typed without forcing you to test if values are nil everywhere.
当你用foo = nil测试你的可选值时它实际上是在返回foo。isNil,当你说foo!这是返回foo。具有foo的断言的realObject。isNil = = false。注意这一点很重要,因为如果foo实际上是nil,那么foo!,这是一个运行时错误,所以通常您需要使用条件let,除非您非常确定该值不是nil。这种欺骗意味着语言可以被强类型输入,而不需要测试值是否为nil。
In practice, it doesn't truly behave like that because the work is done by the compiler. At a high level there is a type Foo?
which is separate to Foo
, and that prevents funcs which accept type Foo
from receiving a nil value, but at a low level an optional value isn't a true object because it has no properties or methods; it's likely that in fact it is a pointer which may by NULL(0) with the appropriate test when force-unwrapping.
实际上,它并不是那样的,因为工作是由编译器完成的。在高水平上有一个类型Foo?它是独立于Foo的,这阻止了接受Foo类型的函数接收nil值,但在较低的层次上,可选值不是真正的对象,因为它没有属性或方法;实际上,它很可能是一个指针,在强制展开时,它的值可能为NULL(0),并带有适当的测试。
There other situation in which you'd see an exclamation mark is on a type, as in:
在其他情况下,你会看到一个感叹号在一个类型上,如:
func foo(bar: String!) {
print(bar)
}
This is roughly equivalent to accepting an optional with a forced unwrap, i.e.:
这大致相当于接受带有强制展开的可选选项,即:
func foo(bar: String?) {
print(bar!)
}
You can use this to have a method which technically accepts an optional value but will have a runtime error if it is nil. In the current version of Swift this apparently bypasses the is-not-nil assertion so you'll have a low-level error instead. Generally not a good idea, but it can be useful when converting code from another language.
您可以使用它来拥有一个方法,该方法技术上接受一个可选值,但如果它是nil,则会有一个运行时错误。在当前版本的Swift中,这显然绕过了is-not-nil断言,因此您将得到一个低级错误。一般来说,这不是一个好主意,但是当从另一种语言转换代码时,它是有用的。
#10
3
The ! means that you are force unwrapping the object the ! follows. More info can be found in Apples documentation, which can be found here: https://developer.apple.com/library/ios/documentation/swift/conceptual/Swift_Programming_Language/TheBasics.html
!意思是你正在用力把物体打开!遵循。更多信息可以在苹果文档中找到,可以在这里找到:https://developer.apple.com/library/ios/documentation/swift/conceptual/swift_programming_language/basics.html
#11
3
If you're familiar with C#, this is like Nullable types which are also declared using a question mark:
如果您熟悉c#,这类似于可以空的类型,也使用问号声明:
Person? thisPerson;
And the exclamation mark in this case is equivalent to accessing the .Value property of the nullable type like this:
在本例中,感叹号等同于访问可空类型的.Value属性,如下所示:
thisPerson.Value
#12
2
In objective C variables with no value were equal to 'nil'(it was also possible to use 'nil' values same as 0 and false), hence it was possible to use variables in conditional statements (Variables having values are same as 'TRUE' and those with no values were equal to 'FALSE').
在objective C中,没有值的变量等于nil(也可以使用0和false的nil值),因此也可以在条件语句中使用变量(值为TRUE的变量和值为false的变量)。
Swift provides type safety by providing 'optional value'. i.e. It prevents errors formed from assigning variables of different types.
Swift通过提供“可选值”提供类型安全。也就是说,它可以防止由于分配不同类型的变量而产生的错误。
So in Swift, only booleans can be provided on conditional statements.
因此,在Swift中,只能在条件语句中提供布尔值。
var hw = "Hello World"
Here, even-though 'hw' is a string, it can't be used in an if statement like in objective C.
在这里,即使“hw”是一个字符串,也不能在objective C中的if语句中使用。
//This is an error
if hw
{..}
For that it needs to be created as,
为此,它需要创建为,
var nhw : String? = "Hello World"
//This is correct
if nhw
{..}
#13
2
The ! at the end of an object says the object is an optional and to unwrap if it can otherwise returns a nil. This is often used to trap errors that would otherwise crash the program.
!在对象的末尾,表示对象是可选的,如果它可以返回nil,则打开该对象。这通常用于捕捉错误,否则会导致程序崩溃。
#14
2
In Short (!): After you have declare a variable and that you are certain the variable is holding a value.
简而言之(!):在声明一个变量并确定该变量持有一个值之后。
let assumedString: String! = "Some message..."
let implicitString: String = assumedString
else you would have to do this on every after passing value...
否则,在传递值之后,您将不得不对每个对象执行此操作……
let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // requires an exclamation mark
#15
1
John is an optional Person, meaning it can hold a value or be nil.
John是一个可选的人,这意味着它可以持有一个值或为nil。
john.apartment = number73
is used if john is not an optional. Since john is never nil we can be sure it won't call apartment on a nil value. While
如果john不是可选的,则使用。因为约翰从来都不是nil,我们可以确定它不会以nil值调用公寓。而
john!.apartment = number73
promises the compiler that john is not nil then unwraps the optional to get john's value and accesses john's apartment property. Use this if you know that john is not nil. If you call this on a nil optional, you'll get a runtime error.
向编译器保证john不是nil,然后打开可选项获取john的值并访问john的公寓属性。如果你知道约翰不是nil,就用这个。如果你在一个空选项中调用这个,你会得到一个运行时错误。
The documentation includes a nice example for using this where convertedNumber is an optional.
文档中有一个很好的例子,可以使用convertedNumber是可选的。
if convertedNumber {
println("\(possibleNumber) has an integer value of \(convertedNumber!)")
} else {
println("\(possibleNumber) could not be converted to an integer")
}
#16
1
To put it simply, exclamation marks mean an optional is being unwrapped. An optional is a variable that can have a value or not -- so you can check if the variable is empty, using an if let statement as shown here, and then force unwrap it. If you force unwrap an optional that is empty though, your program will crash, so be careful! Optionals are declared by putting a question mark at the end of an explicit assignment to a variable, for example I could write:
简单地说,感叹号意味着一个可选项正在展开。可选是一个变量,它可以有值也可以没有值——所以您可以使用if let语句检查变量是否为空,然后强制展开它。如果您强制打开一个可选的空包装,您的程序将崩溃,所以要小心!选项是通过在变量的显式赋值的末尾加一个问号来声明的,例如,我可以这样写:
var optionalExample: String?
This variable has no value. If I were to unwrap it, the program would crash and Xcode would tell you you tried to unwrap an optional with a value of nil.
这个变量没有值。如果我打开它,程序会崩溃,Xcode会告诉你你试图打开一个可选的,值为nil。
Hope that helped.
希望帮助。
#17
1
IN SIMPLE WORDS
用简单的单词
USING Exclamation mark indicates that variable must consists non nil value (it never be nil)
使用感叹号表示变量必须包含非nil值(它从不是nil)
#18
1
The entire story begins with a feature of swift called optional vars. These are the vars which may have a value or may not have a value. In general swift doesn't allow us to use a variable which isn't initialised, as this may lead to crashes or unexpected reasons and also server a placeholder for backdoors. Thus in order to declare a variable whose value isn't initially determined we use a '?'. When such a variable is declared, to use it as a part of some expression one has to unwrap them before use, unwrapping is an operation through which value of a variable is discovered this applies to objects. Without unwrapping if you try to use them you will have compile time error. To unwrap a variable which is an optional var, exclamation mark "!" is used.
整个故事以斯威夫特的一个特点开始,叫做可选vars。这些vars可能有价值,也可能没有价值。一般来说,swift不允许我们使用未初始化的变量,因为这可能导致崩溃或意想不到的原因,并且服务器是后门的占位符。因此,为了声明一个最初未确定值的变量,我们使用'?'。当声明这样一个变量时,要将其作为某个表达式的一部分,必须在使用之前展开它们,展开是一个操作,通过这个操作可以发现一个变量的值,并将其应用于对象。如果您试图使用它们,没有展开包装,您将会有编译时错误。要打开可选的变量var,使用感叹号“!”。
Now there are times when you know that such optional variables will be assigned values by system for example or your own program but sometime later , for example UI outlets, in such situation instead of declaring an optional variable using a question mark "?" we use "!".
现在有些时候,你知道这些可选的变量将被系统分配给你自己的程序,或者你自己的程序,但是在以后的某个时候,比如UI,在这样的情况下,而不是用问号来声明一个可选的变量,我们用“!”
Thus system knows that this variable which is declared with "!" is optional right now and has no value but will receive a value in later in its lifetime.
因此系统知道这个用“!”声明的变量现在是可选的,并且没有任何值,但是在以后的生命中会收到一个值。
Thus exclamation mark holds two different usages, 1. To declare a variable which will be optional and will receive value definitely later 2. To unwrap an optional variable before using it in an expression.
因此,感叹号有两个不同的用法:1。要声明一个变量,该变量将是可选的,并且在以后一定会收到值2。在表达式中使用可选变量之前展开可选变量。
Above descriptions avoids too much of technical stuff, i hope.
我希望上面的描述避免了太多的技术性的东西。
#19
1
If you use it as an optional, it unwraps the optional and sees if something is there. If you use it in an if-else statement is is code for NOT. For example,
如果您将它用作可选项,它将打开可选项,并查看是否存在某些内容。如果在If -else语句中使用它,则是不使用代码。例如,
if (myNumber != 3){
// if myNumber is NOT 3 do whatever is inside these brackets.
)
#20
1
An Optional variable may contain a value or may be not
可选的变量可能包含一个值,也可能不是。
case 1: var myVar:String? = "Something"
案例1:var myvar#:字符串?= "东西"
case 2: var myVar:String? = nil
案例2:var myvar#:字符串?= nil
now if you ask myVar!, you are telling compiler to return a value in case 1 it will return "Something"
如果你问myVar!,你告诉编译器返回一个值,在情况1中它会返回“某物”
in case 2 it will crash.
在第二种情况下它会崩溃。
Meaning ! mark will force compiler to return a value, even if its not there. thats why the name Force Unwrapping.
的意思!mark将强制编译器返回一个值,即使它不在那里。这就是为什么“力量”这个名字被拆开的原因。
#21
0
Simple the Optional variable allows nil to be stored.
var str : String? = nil
str = "Data"
To convert Optional to the Specific DataType, We unwrap the variable using the keyword "!"
func get(message : String){
return
}
get(message : str!) // Unwapped to pass as String
#22
-1
ASK YOURSELF
问问你自己
- Does the type
person?
have anapartment
member/property? OR - 类型的人吗?有一个公寓成员/财产吗?或
- Does the type
person
have anapartment
member/property? - 类型的人有公寓成员/财产吗?
If you can't answer this question, then continue reading:
如果你不能回答这个问题,继续阅读:
To understand you may need super-basic level of understanding of Generics. See here. A lot of things in Swift are written using Generics. Optionals included
要理解泛型,您可能需要非常基本的泛型理解。在这里看到的。Swift中的许多内容都是使用泛型编写的。可选的包括
The code below has been made available from this Stanford video. Highly recommend you to watch the first 5 minutes
下面的代码可以从斯坦福大学的这段视频中找到。强烈建议你看前5分钟
An Optional is an enum with only 2 cases
enum Optional<T>{
case None
case Some(T)
}
let x: String? = nil //actually means:
let x = Optional<String>.None
let x :String? = "hello" //actually means:
let x = Optional<String>.Some("hello")
var y = x! // actually means:
switch x {
case .Some(let value): y = value
case .None: // Raise an exception
}
Optional binding:
let x:String? = something
if let y = x {
// do something with y
}
//Actually means:
switch x{
case .Some(let y): print)(y) // or whatever else you like using
case .None: break
}
when you say var john: Person?
You actually mean such:
你说var john: Person?你的意思是这样的:
enum Optional<Person>{
case .None
case .Some(Person)
}
Does the above enum have any property named apartment
? Do you see it anywhere? It's not there at all! However if you unwrap it ie do person!
then you can ... what it does under the hood is : Optional<Person>.Some(Person(name: "John Appleseed"))
上述全会是否有任何财产命名公寓?你在哪儿见过它吗?根本不存在!但是如果你打开它(做人)!然后你可以…它的作用是:可选的
Had you defined var john: Person
instead of: var john: Person?
then you would have no longer needed to have the !
used, because Person
itself does have a member of apartment
你定义了var john: Person而不是var john: Person吗?那么你就不再需要拥有!使用,因为人本身就有一个公寓成员
As a future discussion on why using !
to unwrap is sometimes not recommended see this Q&A
作为未来讨论为什么使用!有时不建议打开这个问题