user1094081
user1094081

Reputation:

Is the question mark required?

I was reviewing the code of an ex-collegue, when I found this one:

if task != nil {
            // why is "?" here?
            task?.cancel()
            task = nil
        }

task is declared as an optional.

I'm supposing at that point task can't be nil anymore. So why the developer puts a question mark? Couldn't I insert an exclamation mark, instead?

Upvotes: 0

Views: 170

Answers (5)

user3608500
user3608500

Reputation: 835

You can unwrap the optional using if let or guard, then you don't need ? or !

Upvotes: 0

Salman Ghumsani
Salman Ghumsani

Reputation: 3657

Due to compiler hint the ? may be put by the compiler, not your colleague.

Instead, you could use an if let statement as follows:

if let task2 = task {
    task2.cancel()
    task = nil
}

The task is calling cancel() so that may be task is nil, here we notify to the compiler by ? for the task, If the compiler will get nil it goes silently without crashing.

Upvotes: 3

dfrib
dfrib

Reputation: 73186

Thanks for pointing this out but cancel is not mutating and task is a reference type

You've mentioned that task is a reference type, so the optional binding methods show in the other answers will be ok even due to the copying/binding that occurs when optionally binding and mutating a value. Note, however, that you needn't necessarily resort to optional binding to cover the logic in the snippet you've shown, but can instead simply combine the optional chaining and the nil check within a single conditional (and only setting the property to nil within the body of the conditional).

// if task is non-nil, cancel it and set it to 'nil'
// if task is already nil, do nothing
if task?.cancel() != nil { task = nil }

Upvotes: 1

Kegham K.
Kegham K.

Reputation: 1614

You can unwrap optional using Guard statements too

    //This will not unwrap the optional. It will remain optional
    if task != nil {   
       task?.cancel() //That is why the compiler added the question mark automatically 
    }



   // This will unwrap the optional variable
    guard let task2 = task else {
       return
    }

    // task will be optional but task2 will not

    task?.cancel()
    task? = nil

    task2.cancel()
    task2 = nil

Upvotes: 0

Guy Daher
Guy Daher

Reputation: 5601

You should unwrap the value by doing: if let task = task if you want to avoid the question mark.

Upvotes: 0

Related Questions