Skip to content

Instantly share code, notes, and snippets.

@scott-lydon
Last active January 10, 2022 19:39
Show Gist options
  • Save scott-lydon/1d5130def413fafb9076d0c92d7b9f48 to your computer and use it in GitHub Desktop.
Save scott-lydon/1d5130def413fafb9076d0c92d7b9f48 to your computer and use it in GitHub Desktop.
Unwrap methods: force.

Alternative 1: Force unwrap non-optional dependencies

PROs:

  • No need no use any methods to unwrap on each usage, unless there are cases you anticipate a value to be nil.
var value: String!
value = "Hi"
print(value.count) 
  • A crash is a clear signal which may help with debugging by signalling a value was not set which should have been.
var greeting: String!
print(greeting.count)

produces:

__lldb_expr_17/Crash.playground:4: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value

CONs:

  • Greater than 0% risk of a runtime crash on production for now and for future developers.

    • If the value is set to nil.
    var greeting: String! = "hi"
    greeting = nil
    print(greeting.count)
    • If the value is dereferenced (This can happen even in some cases with IBOutlets labeled weak which is why you always want them strong).
    @IBOutlet weak var label: UILabel! 
    ...
    print(label.text) // <crash due to label being dereferenced. 
    • If the assignment of a value is moved to a later point after a read would occur.
    var greeting: String!
    print(greeting.count)
    greeting = "Hi!" // moved from line 2
    • If a read is placed before the assignment of the value.
    var greeting: String!
    print(greeting.count) // moved from line 3
    greeting = "Hi!" 
  • Appears accidental and can confuse developers.

    var greeting: String! // Hmm... Did they intend to force unwrap? Did they look at all the considerations? 
    print(greeting.count)
    greeting = "Hi!" 
  • The type system will allow other developers to use it as though it has 0% chance of being nil, thus it:

    otherLabel.text = "\(greeting.count)" // You or me.  
    ...
    var greeting: String! // Surprise! `greeting` isn't assured to be non-nil.  
  • Requires future developers to identify threats and permutations to gain assurances that a crash does not occcur in production.

     var greeting: String! // Oh, boy, I need to work with this property.. but I need to study all the possible risks and permutations of when this could be nil so that I don't introduce a crash just by using it.  
  • Doesn't show where a property or variable wasn't assigned a value but should have been, nor where it was dereferenced, nor when it was assigned to nil.

var greeting: String!
print(greeting.count)

produces:

__lldb_expr_17/Crash.playground:4: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value

But that ^ doesn't tell me where the value should have been assigned, nor where it was dereferenced, nor when it was assigned to nil. Which is the bulk of the work for debugging this kind of issue.

  • There are alternatives. For example:
if money == nil {
    fatalAssertion("money should never be nil.  We need to crash here to prevent a transaction which might not be supported).  
}

Has intentionality and doesn't confuse other developers.

  • Usage for force unwrap sometimes encourages force unwrap for other times.
var greeting: String!

Hey someone used force unwrap... Thats easy!

var myGreeting: String!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment