What does an exclamation mark mean in the Swift la

2018-12-31 06:29发布

The Swift Programming Language guide has the following example:

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":

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.

22条回答
与风俱净
2楼-- · 2018-12-31 06:42

John is an optional Person, meaning it can hold a value or be 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!.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.

The documentation includes a nice example for using this where convertedNumber is an optional.

if convertedNumber {
    println("\(possibleNumber) has an integer value of \(convertedNumber!)")
} else {
    println("\(possibleNumber) could not be converted to an integer")
}
查看更多
零度萤火
3楼-- · 2018-12-31 06:43

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
查看更多
余欢
4楼-- · 2018-12-31 06:44

IN SIMPLE WORDS

USING Exclamation mark indicates that variable must consists non nil value (it never be nil)

查看更多
听够珍惜
5楼-- · 2018-12-31 06:44

An Optional variable may contain a value or may be not

case 1: var myVar:String? = "Something"

case 2: var myVar:String? = nil

now if you ask myVar!, you are telling compiler to return a value in case 1 it will return "Something"

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.

查看更多
十年一品温如言
6楼-- · 2018-12-31 06:45

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

查看更多
梦该遗忘
7楼-- · 2018-12-31 06:46

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.

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.

Update:

Getting back to this answer after 4 years, as I got the highest reputations from it in Stackoverflow :) 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.

查看更多
登录 后发表回答