What does an exclamation mark mean in the Swift language?

后端 未结 22 2182
南方客
南方客 2020-11-22 03:47

The Swift Programming Language guide has the following example:

class Person {
    let name: String
    init(name: String) { self.name = name }
    var apar         


        
相关标签:
22条回答
  • 2020-11-22 04:09

    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
    
    0 讨论(0)
  • 2020-11-22 04:10

    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:

    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.

    Hope that helped.

    0 讨论(0)
  • 2020-11-22 04:11

    If you're familiar with C#, this is like Nullable types which are also declared using a question mark:

    Person? thisPerson;
    

    And the exclamation mark in this case is equivalent to accessing the .Value property of the nullable type like this:

    thisPerson.Value
    
    0 讨论(0)
  • 2020-11-22 04:12

    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 if 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.

    0 讨论(0)
  • 2020-11-22 04:12

    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.

    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.

    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.

    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.

    0 讨论(0)
  • 2020-11-22 04:12

    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

    0 讨论(0)
提交回复
热议问题