Quantcast
Channel: Kodeco | High quality programming tutorials: iOS, Android, Swift, Kotlin, Unity, and more
Viewing all articles
Browse latest Browse all 4387

Swift Style Guide: April 2016 Update

$
0
0
Swift Style Guide--it is fun to talk about!

Style–it’s fun to talk about!

Good news – we have updated our popular Swift Style Guide for Swift 2.2!

Here at raywenderlich.com, we want to have a consistent style for you in our tutorials, books, videos, and conference materials. We believe it improves readability, and makes our content easier and quicker to understand.

At the same time, we want to avoid making a style guide so strict that an author feels like they are wearing a straight-jacket!

We’ve tried our best to walk this line carefully, and you may even wish to adopt some of these standards in your own projects. That said, our style guide is different than other style guides; we’re a tutorial site, which means our priorities are making our code easily readable in printed books and on the web. Many of the decisions are made with an eye toward conserving space for print, legibility, and tutorial writing.

Since our last major style update in April 2015, readers and team members opened dozens of issues against the guide and generated long threads of discussion suggesting how things could be made better. While we could not adopt all of the suggestions, we are truly grateful for feedback and the thoughts it generated. We hope you find this to be a compelling update.

Let’s look at some of the highlights.

Crush the Warnings

In a way, the Swift evolution community sets its own minimal style guidelines by causing the compiler to emit warnings on deprecated language features. You should consider warnings to be errors and fix them.

I am always surprised when I jump on a new project and find that the previous developer didn’t take the time to fix the warnings. We all have deadlines, but don’t let this be you. :]

Swift 2.2 brought several deprecations. For example, the ++ and -- operators along with along with the C-style for-loop are slated for removal in Swift 3. Rather than falling back to using a while-loop, go ahead and use enumerate() or the full power of ranges. It’s easy and fun. For example:

// list the index and item
for (index, item) in items.enumerate() {
  print("\(index): \(item)")
}
 
// count up from zero up to items.count by twos
for index in 0.stride(to: items.count, by: 2) {
  print(index)
}
 
// count down from three to zero
for index in (0...3).reverse() {
  print(index)
}

Another deprecation includes using strings instead of the new #selector expression. Xcode’s “fix it” button helps you out here, but it always uses the fully qualified names. Usually you can take advantage of context to make it shorter and more readable. Make the extra effort.

Less is more: The Swift evolution community is doing great work not only expanding features of Swift but also removing the less useful ones and simplifying the language as well. 🎉

Mind the Golden Path

The Golden Path (or sometimes Happy Path) rule dates back to our Obj-C style guide. It refers to the notion that you don’t want to nest conditional statements too deeply. That quickly gets hard to read.

// Not preferred
func computeFFT(context: Context?, inputData: InputData?) throws -> Frequencies {
 
  if let context = context {
    if let inputData = inputData {
      // use context and input to compute the frequencies
 
      return frequencies
    }
    else {
      throw FFTError.NoInputData
    }
  }
  else {
    throw FFTError.NoContext
  }
}

If you can help it, don’t nest at all. Embrace the concept of the early exit.

Every major release of Swift: 1.0 with optional chaining, 1.2 with multiple let optional binding and 2.0 with the guard, throws and defer statements have given you increasingly better tools to build a clean, readable golden paths through your methods. Use them!

// Preferred
func computeFFT(context: Context?, inputData: InputData?) throws -> Frequencies {
 
  guard let context = context else { throw FFTError.NoContext }
  guard let inputData = inputData else { throw FFTError.NoInputData }
 
  // use context and input to compute the frequencies
 
  return frequencies
}

Advantages of Being Lazy

Swift is a “safe” language. This means, among other things, that your objects are always guaranteed to be fully initialized before you use them. The rules can sometimes get a bit tricky. In fact, you might want to consult out our Swift Initialization in Depth tutorial if you want to understand the finer points of the process.

With UIViewControllers, full initialization is often delayed until the views load. Lazy initialization is a handy (and often safer) approach to use.

Consider the following stored property in your view controller:

lazy var locationManager: CLLocationManager = {
    let manager = CLLocationManager()
    manager.desiredAccuracy = kCLLocationAccuracyBest
    manager.delegate = self
    manager.requestAlwaysAuthorization()
    return manager
}()

This allows you to defer initialization until you actually refer to the stored property which might have side-effects such as a permissions popup to appear.

Lifetime Extension

caretodance

When you are dealing with asynchronous requests such as a network call and then use that data to update your UI it is easy to inadvertently create a retain cycle. (Heap leak!)

Swift cleverly makes you explicitly type out self to clue you in that you might be doing this. Swift also lets you supply a capture list to break the retain cycle.

Be very careful using [unowned self] in your capture list. If your UI doesn’t outlive your network request, you just created an asynchronous crasher. Instead, prefer the more bulletproof [weak self].

In your closure, rather than optionally unwrap self each time, extend lifetime by performing the so-called strong-weak dance. This results in fewer possible code paths so is more obviously correct. An example of the canonical strong-weak dance is:

resource.request().onComplete { [weak self] response in
  guard let strongSelf = self else { return }
  let model = strongSelf.updateModel(response)
  strongSelf.updateUI(model)
}

We converged on the constant name strongSelf by looking at what a few successful open source projects (such as Alamofire) were doing. Perhaps in the future there will be a language feature to help minimize this boilerplate. For now, extending lifetime using the strong-weak dance ensures that you don’t create a retain cycle and that you don’t crash.

Flip Flops

Part of being a good style guide is to keep up with the changes in Swift as they come. In this update of the style guide we tell you to do a couple of things exactly opposite of what we said in the past. Sorry. :]

For example, although the style guide still recommends using type inference rather than an explicit type annotation in most cases, initializing arrays an dictionaries is now different. The new preferred form is:

var names: [String] = []
var lookup: [String: Int] = [:]

Many publications, including Apple, now use this form. Even Swift engineer extraordinaire, Joe Groff was kind enough to chime in on this issue.

Another flip-flop is in the capitalization of enumerations. Following Apple’s lead, before we said to use UpperCamelCase. Now, in anticipation of the Swift 3 API Design Guidelines, lowerCamelCase is preferred. The rationale is that cases are values and should follow the same convention as other values. Since Xcode won’t fight you on the matter, we might as well adopting now. We welcome our new Optional .some and .none overlords when Swift 3 appears this Fall.

Where to Go From Here?

This style guide update contains a lot of smaller but important details not covered here: names of generic types, chaining closures, defining constants and more. Over time, you will see our tutorials and books adopt this style.

We encourage you to read through the entire guide as it is not that long. If there is something you like (or don’t), let us know in the comments below.

If you want to get even more involved, open a Github issue and start a community discussion on a specific issue. You can even create a pull request. Typos and errors that need to be immediately fixed will go directly into the master branch after a brief review period. A swift3 branch will handle changes for a future update this Fall.

Herb Sutter and Andrei Alexandrescu famously admonish:

"Think. Do follow good guidelines conscientiously; but don’t follow them blindly."

This is great advice; no set of programming guidelines can cover every use case. Exceptions will always exist. In addition to helping you read our code, we hope that this style guide helps authors worry less about the mundane and focus on more interesting things. Enjoy!

The post Swift Style Guide: April 2016 Update appeared first on Ray Wenderlich.


Viewing all articles
Browse latest Browse all 4387

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>