I am new to swift so this is definitely a newbie level question. I was pondering on some Swift 3.0 documentation where I noticed a potential error. I am wondering if the example is incorrect (or ambiguous) or I am in fact missing out on some guideline.
See http://swiftdoc.org/v3.0/type/Optional/ the section about Optional Chaining.
OPTIONAL CHAINING
To safely access the properties and methods of a wrapped instance, use the postfix optional chaining operator (
?
). The following example uses optional chaining to access thehasSuffix(_:)
method on aString?
instance.if let isPNG = imagePaths["star"]?.hasSuffix(".png") { print("The star image is in PNG format") } // Prints "The star image is in PNG format"
AFAIU, imagePaths["star"]?.hasSuffix(".png")
is only supposed to safely unwrap imagePaths
and run hasSuffix()
only if imagePaths["star"]
results in Optional.some(wrapped)
. This implies that isPNG
will be either true
or false
. Therefore, the implication of the above sample is incorrect where it implicitly claims that if this safely unwraps, then the value is always true.
Here are some examples to explain what I am talking about:
if let isPNG = imagePaths["star"]?.hasSuffix(".png") {
print("The star has png format")
} else {
print("The star does not have png format")
}
if let isPNG = imagePaths["portrait"]?.hasSuffix(".png") {
print("The portrait has png format")
} else {
print("The portrait does not have png format")
}
// "The portrait has png format\n"
if let isPNG = imagePaths["alpha"]?.hasSuffix(".png") {
print("The alpha has png format")
} else {
print("The alpha does not have png format")
}
// "The alpha does not have png format\n"
I am simply wondering if my current analysis is wrong or if SwiftDoc.org needs to change this particular example.
Your analysis is correct, and the example at SwiftDoc.org is at least misleading, as the following code demonstrates:
let imagePaths = ["star": "image1.tiff"]
if let isPNG = imagePaths["star"]?.hasSuffix(".png") {
print("The star has png format")
} else {
print("The star does not have png format")
}
// Output: The star has png format
The optional binding succeeds if
imagePaths["star"]?.hasSuffix(".png")
is not nil
, and that is if the optional chaining could be executed, i.e. if imagePaths["star"] != nil
.
A correct way to test for all situations would be
if let isPNG = imagePaths["star"]?.hasSuffix(".png") {
if isPNG {
print("The star has png format")
} else {
print("The star does not have png format")
}
} else {
print("No path in dictionary")
}
Of course this can be simplified in various ways (nil-coalescing operators, pattern matching, ...). For example
switch(imagePaths["star"]?.hasSuffix(".png")) {
case true?:
print("The star has png format")
case false?:
print("The star does not have png format")
case nil:
print("No path in dictionary")
}
or
let isPNG = imagePaths["star"]?.hasSuffix(".png") ?? false
(More examples in the comments to the question.)
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments