barndog
barndog

Reputation: 7183

Semantics between optional and non-optional function parameters in Swift and best use cases

I've seen a lot of discussion regarding variables in Swift that are declared as var a: String? and var a: String! the former being an optional variable of type String and the latter being implicitly unwrapped optional String. From my understanding, when something is implicitly unwrapped there's an assumption being made that there's a value already included in the optional value. In order to use the syntax a!.toInt() there would have to be an outside check like so:

if a != nil {
   a!.toInt()
}

As a side note, it seems better practice to just declare variables as an optional type and then use optional chaining to unwrap the value if it exists. Doing:

if let numberString = a?.toInt() {
    numberString.toInt()
}

Is there a scenario in where accessing a variable like a!.toInt() should ever be used in practical applications? To me, it seems like you'd be asking for runtime errors.

Now for the actual question. I was looking through the documentation, specifically enumerateObjectsUsingBlock on NSArray and the block parameter is declared using an !. Does this mean that the writers of that function are assuming that the block parameter will be non-nil? If so, inside that function, what is the semantic difference between:

func someMethodWithBlock(block:((String!)-> Void)!) {
     var a = "Hello"
     block.(a) //first syntax example
     block?.(a)//2nd
     block!.(a)//3rd
}

Upvotes: 1

Views: 328

Answers (1)

jtbandes
jtbandes

Reputation: 118761

Implicitly Unwrapped Optionals are used almost everywhere in the Cocoa APIs as they are imported into Swift — this is to maintain compatibility with the kind of pointer semantics that are ubiquitous in Obj-C, without requiring !s and ?s all over the place. That's why the NSArray method's block takes a String! argument.

In Swift, regular Optionals (Int?, etc.) are largely preferable for the reasons you specified: they are less prone to errors. Implicitly Unwrapped Optionals are mostly meant to be used only in certain cases, like when you need to pass self to a function before initialization is complete. (If you know a variable is not nil, unwrapping it like a!.toInt() is just fine. The danger with IUOs is that it would be written a.toInt(), and to a reader this looks completely safe, when in reality it's not.)

Upvotes: 2

Related Questions