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)

然后,在给这个人分配公寓时,他们使用感叹号来“打开实例”:

john!.apartment = number73

“展开实例”是什么意思?为什么有必要?它与仅仅做以下事情有什么不同:

john.apartment = number73

我对Swift语言很不熟悉。我只是想把基本的东西记下来。

更新: 我遗漏了一个很大的谜团(答案中没有直接说明——至少在写这篇文章的时候没有),那就是当你做以下事情的时候:

var john: Person?

这并不意味着“约翰是人的类型,它可能是nil”,因为我最初的想法。我只是误解了《人与人》是完全不同的类型。一旦我明白了,所有其他的?,!疯狂,以及下面这些精彩的回答,让我觉得更有道理。


当前回答

!在对象的末尾表示该对象是可选的,如果它可以返回nil则展开。这通常用于捕获错误,否则会使程序崩溃。

其他回答

如果你来自c语言家族,你会想“指向X类型对象的指针,它可能是内存地址0 (NULL)”,如果你来自动态类型语言,你会想“对象可能是X类型,但可能是未定义的类型”。这两种说法实际上都不正确,尽管迂回地说,第一个说法很接近。

你应该把它想象成一个物体:

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?它与Foo是分开的,这可以防止接受类型Foo的函数函数接收到nil值,但在低级别上,可选值不是一个true对象,因为它没有属性或方法;实际上,它很可能是一个指针,在强制展开时,通过适当的测试,它可能是NULL(0)。

还有一种情况,你会看到感叹号是在一种类型上,比如:

func foo(bar: String!) {
    print(bar)
}

这大致相当于接受一个强制展开的可选选项,即:

func foo(bar: String?) {
    print(bar!)
}

你可以使用它来创建一个方法,该方法在技术上接受一个可选值,但如果它为nil,则会出现运行时错误。在当前版本的Swift中,这显然绕过了is-not-nil断言,所以你会有一个低级错误。通常不是个好主意,但在从另一种语言转换代码时可能很有用。

!意味着您正在强制打开对象!遵循。更多信息可以在苹果文档中找到,可以在这里找到:https://developer.apple.com/library/ios/documentation/swift/conceptual/Swift_Programming_Language/TheBasics.html

John是一个可选的变量,它可以包含一个nil值。要确保该值不是nil,请使用a !在var名称的末尾。

从文档

一旦您确定可选选项确实包含一个值,您可以通过在可选选项名称的末尾添加一个感叹号(!)来访问它的底层值。感叹号有效地表示,“我知道这个可选选项肯定有价值;请使用它。”

另一种检查非nil值的方法是(可选的展开)

    if let j = json {
        // do something with j
    }

简单地说,感叹号意味着一个可选选项正在被打开。可选变量是一个可以有值也可以没有值的变量——因此,您可以使用如下所示的if let语句检查变量是否为空,然后强制展开它。如果你强制打开一个空的可选选项,你的程序会崩溃,所以要小心!可选项是通过在变量的显式赋值后面加一个问号来声明的,例如我可以这样写:

var optionalExample: String?

这个变量没有值。如果我要打开它,程序会崩溃Xcode会告诉你你试图打开一个值为nil的可选对象。

希望这有帮助。

可选变量可以包含值,也可以不包含值

myVar:字符串?= "东西"

myVar:字符串?= nil

现在如果你问myVar!,你告诉编译器返回一个值在情况1中它会返回"Something"

在情况2中,它会崩溃。

的意思!Mark将强制编译器返回一个值,即使它不存在。这就是为什么这个名字叫Force unwrapped。