2

Swift If Case Let

 3 years ago
source link: https://useyourloaf.com/blog/swift-if-case-let/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Swift If Case Let

Dec 21, 2020 · 3 minute read

The Swift If-Case-Let syntax is a convenient shortcut to avoid a full switch statement when you only want to match a single case. The syntax always seems backwards to me so here’s a reminder of how to use it.

Case Let - A Recap

I’m using the Swift Result type to capture the results of a throwing expression. In this case, loading data from a file:

let result = Result { try Data(contentsOf: url) }
// result is of type Result<Data, Error>

The Result type is an enum with a success and failure case both of which have an associated value. In my example, I would typically switch on the result:

switch result {
  case .success(let data):
    completion(data)

  case .failure(let error):
    print(error)
}

The let binds the associated value to a variable that we can use in the body of the case. We can also write these as case let:

switch result {
  case let .success(data):
    completion(data)

  case let .failure(error):
    print(error)
}

We can also add a where clause to further filter the matching cases:

  case let .success(data) where data.count > 100:

The case let syntax is not restricted to switch statements. We can rewrite the switch as a series of if-case-let statements if we want:

// if statement
if case let .success(data) = result { ... }

// if statement - alternate form
if case .success(let data) = result { ... }

// if statement with extra condition
if case let .success(data) = result, data.count > 100 { ... }

Note that the value we were switching on (result) now becomes an initializer for the case statement. The last example written as a guard statement:

// guard statement
guard case let .success(data) = result, data.count > 100 else { 
  return
}

Finally, here’s an example of a for-in loop:

// for-in loop
for case let score in scores where score > 4 { ... }

Replacing A Switch With If Case Let

A switch statement is fine when I have something to do for all (or most) of the cases. Here’s an example where I only care about the failure case. I’m encoding some model data and then writing it to a property list file:

let result = PropertyListEncoder.encode(countries)
            .flatMap { Data.write($0, to: url) }

The Data.write method is an extension I added on Data that converts the throwing data.write(to:) method to return a result of type Result<void,Error>. It either succeeds, returning void, or fails with an error. Switching over the result in this case is annoying:

switch result {
case .success():
  // Nothing to do here

case .failure(let error):
  // Handle error
  print(error)
}

Using the case-if-let syntax to replace the switch statement:

if case let .failure(error) = result {
  // Handle error
  print(error)
}

Or using the alternate version which I find slightly easier to remember as it’s closer to the original switch syntax:

if case .failure(let error) = result {
  // Handle error
  print(error)
}

I still find using the result value as the initializer for the case-let confusing but I prefer it over the more verbose switch version. What do you think? Do you have a favorite use for case let?

Never Miss A Post

Sign up to get my iOS posts and news direct to your inbox and I'll also send you a PDF of my WWDC Viewing Guide

wwdc2020.png

Unsubscribe at any time. See privacy policy.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK