Is Swift optional chaining always done with the if let construction, or is it just done using a question mark with an optional?

試著忘記壹切 提交于 2021-02-07 03:55:45

问题


As per Apple docs, optional chaining is the following:

You specify optional chaining by placing a question mark (?) after the optional value on which you wish to call a property, method or subscript if the optional is non-nil. ... optional chaining fails gracefully when the optional is nil ...

My interpretation of this is that a construction as the following is optional chaining:

someMasterObject.possiblyNilHandler?.handleTheSituation()

...and that the above line would call the handleTheSituation method if the handler is not nil, and fails gracefully (line skipped) if the handler is nil.

However almost all examples I see of optional chaining use the "if let" construction, as per:

if let handler = someMasterObject.possiblyNilHandler{
  handler.handleTheSituation()
}

In fact, the documentation and examples I have found on the net make such heavy use of the "if let" construction in relation to optional chaining that it seems as if that IS optional chaining.

Am I correct, however, in assuming that my first example is a supported use of optional chaining and that the if let construction is another construction using (or being intimately tied to) optional chaining?


回答1:


The conclusion is correct - let is an independent, but useful, construct. In context it introduces a binding only within the if-body and executes the if-body only if the bound value is not-nil. (Technically it unwraps an optional binding.)

let does not affect how the expression on the right (with or without chaining) is handled. For instance, if someMasterObject were optional/nil it would fail and not "chain" - even with let.

When one or the other (or both) is more "correct" depends on the situation: eg. what is being chained and what the corrective action should be.


For instance, if someMasterObject could be nil, we might have the following which uses both chaining and let. Also note how the return value matters and is not simply discarded or "nil on failure":

if let handler = someMasterObject?.possiblyNilHandler{
  return handler.handleTheSituation()
} else {
  return FAILED_TO_CALL
}

Then compare it with a non-equivalent chained form, which would only return nil in the failed-to-call case, but nil might be a valid return value from handleTheSituation!

return someMasterObject?.possiblyNilHandler?.handleTheSituation()

On the other hand, do consider that there is always direct translation of chaining to nested if-let statements:

result_of_expression = someMasterObject?.possiblyNilHandle?.handleTheSituation()

if let master = someMasterObject {
   if let handler = master.possiblyNilHandler {
       result_of_expression = handler.handleTheSituation()
   } else {
       result_of_expression = nil
   }
} else {
   result_of_expression = nil
}



回答2:


Optional chaining is useful in more cases than just optional binding (if let):

person?.name = "Fred"              // assign "Fred" to name property if person is not nil

person?.congratulate()             // call congratulate method if person is not nil

let name = person?.name ?? "none"  // nil coalescing operator

let age = dict?["age"] ?? 0        // subscripting an optional variable

if var name = person?.name {       // optional binding using var instead of let



回答3:


Calling methods through optional chaining is perfectly alright - you do not need an if around it. If the optional value happens to be nil at the time of the call, your code would not throw an exception. However, you wouldn't be able to find out whether the method has run or not.

However, typically you want to place an if around the optional chaining method call to detect if the method has been called or not:

func printNumberOfRooms() {
    println("The number of rooms is \(numberOfRooms)")
}

if john.residence?.printNumberOfRooms() != nil {
    println("It was possible to print the number of rooms.")
} else {
    println("It was not possible to print the number of rooms.")
}

Link to the book chapter.

Note that the nil check works even though the function in the example has no return value. Since it is called on an optional value using optional chaining, the type is Void?, not Void, which makes the comparison possible.



来源:https://stackoverflow.com/questions/27734612/is-swift-optional-chaining-always-done-with-the-if-let-construction-or-is-it-ju

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!