Why to Avoid Forced Unwrapping

How to avoid force unwrapping a variable?

Use the if let or guard constructs:

func fullName() -> String {
if let middleName = middleName {
return "\(firstName) \(middleName) \(lastName)"

} else {
return "\(firstName) \(lastName)"
}
}

func fullName() -> String {
guard let middleName = middleName else {
return "\(firstName) \(lastName)"
}
return "\(firstName) \(middleName) \(lastName)"
}

I've put the guard statement in for completeness but as others have commented this is more commonly used in an error/failure case.

I would also advise against using string interpolation for Strings. They are already strings, there is no need to use the description of each name in a new string.

Consider return firstName + " " + lastName. See Difference between String interpolation and String initializer in Swift for cases when string interpolation could return an unexpected result.

Is it safe to force unwrap an optional after checking it is not nil

The difference between if and guard is just simple, but in your case, you should use if, not guard. guard should be used when some values are expected to be present for the function to execute as intended. You don't want error to be present, but if it is not nil, you have to return. So you should use if let:

if let error = error {
print(error)
return
}

This way, you don't need to use force unwrapping and it improves how your code is represented.

Back to your question "In general, is this force unwrapping thread safe or not?", assuming that you are really talking about thread safety, it is certainly thread safe. Closure variables are immutable.

If you are talking about safety (ie will "fatal error: unexpectedly found nil while unwrapping an Optional value" occur), it is also certainly safe. error must not be nil before you can unwrap it (because of guard), so the force unwrapping is safe.

In conclusion, your current code is bulletproof, but using if let might be better.

avoid force unwrapping inside a sort closure in Swift

You are sorting in descending order.

Use the nil coalescing operator ?? to safely unwrap the values and replace nil with Int.min to place the items at the end of the array:

// sorting each language array based on most stars
groupedDictionariesValueUnwrapped.sort(by: { ($0.stars ?? Int.min) > ($1.stars ?? Int.min) })

or use ?? Int.max to put them at the beginning.

Why using implicit unwrap or force unwrap letting the app crash at some stage not beneficial?

Sure. There any many proper uses of force-unwrapping where a crash will only occur early in development because a mistake has been made and once fixed, the crash won't ever happen again.

A common example is accessing an image from the resource bundle. A line such as:

let imagePath = Bundle.main.path(forResource: "image", ofType: "png")!

should crash in early development if the developer forgot to target image.png properly. Once targeted properly, that line won't crash so there's no reason to deal with an optional path.

Other common examples are outlets. They are usually made implicitly unwrapped because by the time they are used in the view controller's code, they will have been attached. A crash probably means the outlet wasn't connected properly. It gets fixed and there's no more worry. No need to deal with guards or other optional checking.

Last example (there are many more possibilities). When dequeuing a cell from a table view, force-cast the resulting cell to the custom cell type. No need for a guard. I see code here all the time that uses a guard with as? to throw a fatal error if the cast fails. Just force-cast. You get the same crash with less code. Once the table view and storyboard are correct, the force-cast won't fail.

Having said this, newer Swift developers should avoid the ! character on their keyboard for a while. Knowing when to safely use it is a learned skill.

If the potential crash is fully in the control of the developer and the crash could only happen because the developer make a mistake, then using ! may be appropriate.

If the potential crash can be caused by unexpected data (JSON parsing, user input, etc.), then never use !. Code defensively in those cases.

tl;dr - yes, there are plenty of cases where forced-unwraps, forced-casts, and implicitly unwrapped variables are the correct choice.

avoid force unwrapping inside a filter closure in Swift 4

You can avoid force unwrapping by directly comparing to true:

let tempFilteredResult = keysForAutoComplete.filter { $0?.contains("abc") == true }

or by using the nil coalescing operator ?? to unwrap the result:

let tempFilteredResult = keysForAutoComplete.filter { $0?.contains("abc") ?? false }

or by using the nil coalescing operator ?? to unwrap the input:

let tempFilteredResult = keysForAutoComplete.filter { ($0 ?? "").contains("abc") }

Explanation:

$0?.contains("abc") is using optional chaining and the result is a Bool? which is nil if the element is nil or Optional(true) or Optional(false) depending on whether the String contains "abc". You can compare a Bool? to a Bool, so comparing to true will return true only when there is a String that contains "abc".

The nil coalescing operator unwraps the value if it is not nil, or replaces it with the supplied default value if it is nil. Since you want a nil item to return false for the comparison, the way to safely unwrap is to use ?? false.

In the third example, the nil coalescing operator unwraps the value from tempFilteredResult replacing it with the empty string "" if it is nil.


If you'd like the result to be [String], you can use compactMap along with the trinary operator ?: to generate an array of [String]:

let tempFilteredResult = keysForAutoComplete.compactMap { $0?.contains("abc") == true ? $0 : nil }

Explanation:

Here, ?: is used to return the original value if it contains "abc" or nil if it does not. compactMap then eliminates the nil values and unwraps the String? to return a [String].

Not using unwrapping in guard statements

guard let unwrapped = optional is an Optional Binding (no link available directly to the correct book section, unfortunately). It safely tries to unwrap the value in the optional. If there is a value, the unwrap succeeds, and the value is assigned to the given name.

You should heavily favor the use of optional bindings, with either guard or if (the difference is the scope of the "unwrapped" name) over the use of forced unwrapping with !. A failed force unwrap is a fatal error; your program will simply crash.

Can’t seem to avoid force unwrapping in Swift

You can use optional binding for the file first, and then proceed from there:

if let file = files["textFile.rtf"],
contents = file.regularFileContents,
newString = NSMutableAttributedString(data: contents, options: [NSDocumentTypeDocumentAttribute : NSRTFTextDocumentType], documentAttributes: nil, error: nil) {
text = newString
return true
}

If you're using fileWrappers dictionary (a [NSObject : AnyObject]), you have to do some additional casting. This example is using a file I happen to have in that file wrapper, but hopefully it illustrates the idea:

var text: NSString!

func someMethod(fileWrapper: NSFileWrapper) {
let files = fileWrapper.fileWrappers

if let file = files["test.json"] as? NSFileWrapper,
contents = file.regularFileContents,
newString = NSString(data: contents, encoding: NSUTF8StringEncoding) {
text = newString
println(text)
}
}


Related Topics



Leave a reply



Submit