0

I have one function in Swift like,

func getValue(param: String!) -> String {
    //access param
    //return a string
}

call is like,

let retVal = getValue(param: nil)

I expected that the param will try to force unwrap while taking into the function parameters and get crashed. But the code did not crash. Can anyone let me know what am I missing?

What will be different in case of the signature,

func getValue(param: String?) -> String
Sazzad Hissain Khan
  • 37,929
  • 33
  • 189
  • 256
  • It's strongly discouraged to declare a function parameter as implicit unwrapped optional in a pure Swift environment. If you need an optional, declare a (regular) optional. – vadian Feb 07 '20 at 07:52
  • @vadian whats the reason behind that discouragement? – Sazzad Hissain Khan Feb 07 '20 at 07:54
  • From the documentation: *Implicitly unwrapped optionals are useful when an optional’s value is confirmed to exist immediately after the optional is first defined and can definitely be assumed to exist at every point thereafter*. That's not valid for parameters. And if you are going to pass `nil` you certainly mean a regular optional. IUO parameters are only (enforced) useful for Objective-C interoperability. – vadian Feb 07 '20 at 08:07
  • @vadian got your point, thanks – Sazzad Hissain Khan Feb 07 '20 at 08:12

2 Answers2

4

Here ! means the param will hold String value or nil. So when you assign nil to ! it is not supposed to crash. But when you try to access that value, it will crash.

This modification in your code will cause a crash as we are trying to access the value inside the variable which is nil.

func getValue(param: String!) -> String {
    if param.isEmpty {
        return ""
    }
    return ""
}

let retVal = getValue(param: nil)

Another example:

var string: String!
string = nil //This will not crash, but after this line if you try to access or perform any operation on it, it will

Now about thisfunc getValue(param: String?) :

In this scenario the the param will be optional type unlike in the above scenario. So here you will have to unwrap it.

Sharad Chauhan
  • 4,821
  • 2
  • 25
  • 50
2

Implicitly unwrapped optional (or IUO) may still contain nil as a value! In case of IUO you will get a crash only when you call any method/variable on it (e.g. param.count) OR when you assign it to a NON-Optional variable which will led to force unwrapping operation:

var param: String! = nil
var nonOptionalStr: String = param //<- Crash because it will try to force-unwrap param

Another example of a crash:

func foo(param: String!) -> String {
    return param //<- Crash! As return type is non-optional String it will try to force unwrap the param.
}

On the other hand IUOs (as well as Optionals) are also of type Any so if you pass a String! containing nil to a method which expects Any it will not crash because there will be no force-unwrapping operation as Any? can be easily cast to Any .

let str: String! = nil
print(str) //<-  No Crash! Becaise print accepts Any, so there will be no force-unwrapping
//Output: nil

Another example with type Any:

var a: Any? = nil
var b: Any = a //<- No Crash! As (Any?) is kind of (Any), though you will get a warning from compiler: Expression implicitly coerced from 'Any?' to 'Any'
print(b)
//Output: nil
arturdev
  • 10,884
  • 2
  • 39
  • 67