Bugsee - Free crash and bug reporting for iOS, with video, network and logs. Learn More

Swift Protocols are great. They allow us to express the idea of expecting a set of functionality, without needing to expect a specific concrete type. Today we'll look at creating a Protocol to make working with colors in our apps a bit more flexible. Let's dive in. 🏊

We'll start by creating a new Protocol, giving it a conventional name, and require just one read-only property from our conforming types. This property will always return a UIColor.

public protocol ColorConvertible {
  var colorValue: UIColor { get }
}

Now, let's try this new Protocol out by creating an enum that represents the different colors we use in our app:

public enum SpaceshipsColors : String {
  case white = "FFFFFF"
  case red = "E2574C"
  case gold = "EFC75E"
  case darkTeal = "314D5B"
  case lightTeal = "3CB39E"
  case spaceGray = "233640"
  case aluminum = "6A838D"
  case black = "000000"
}

Looking pretty good, now let's extend our enum to conform to ColorConvertible.

We're using Hue here (Bite #195) to convert our hex color code Strings into UIColors.

extension SpaceshipsColors : ColorConvertible {
  public var colorValue: UIColor {
    return UIColor.hex(rawValue)
  }
}

Now we can reference colors in our code by name, and get full autocompletion when typing them. Using our new Protocol is super simple, let's make a quick UIView subclass to show it off:

class SpaceshipNameHeaderView : UIView {
  var nameLabel: UILabel
  var nameTextColor: ColorConvertible? {
    didSet {
      nameLabel.textColor = nameTextColor?.colorValue
    }
  }
}

It'd be nice if we could still supply "one-off" UIColors as well. No problem, let's simply conform UIColor itself to be ColorConvertible. We can just return self:

extension UIColor : ColorConvertible {
  public var colorValue: UIColor {
    return self
  }
}

Finally, we can use it like this:

let hv = SpaceshipNameHeaderView()

// works!
hv.nameTextColor = UIColor.black

// works just as well!
hv.nameTextColor = SpaceshipsColors.aluminum

Swift Protocols can help us write code that is both expressive and quite flexible. They can take a while to get a handle on, but understanding them is a key step towards unlocking the full power of Swift.

Testing network requests can be tricky. Generating mock data, handling HTTP routes, etc. Thing get complicated quickly. Today we'll check out a library from devlucky called Kakapo that can help us tame all this. Let's get started.

One of the best features of Kakapo is how easy it is start using. We can create a new Router for a domain, and start adding intercepted routes like this:

let router = Router.register("http://littlebitesofcocoa.com")

router.get("/bites") { request in
  return ["id" : 1, "title": "#1: View Controller Initialization 🚀"]
}

In the above example, we're returning static data. Let's kick things up a notch and return some dynamic data. This is another place Kakapo really shines:

let db = KakapoDB()
db.create(Bite.self, number: 10)

router.get("/bites") { request in
  return db.findAll(Bite.self)
}

We can use this functionality to not only test network requests, but even to "stub out" responses before fully implementing backend services. Neat!

Once we've wired up some routes, we can make our network requests like normal:

let URL = NSURL(string: "http://littlebitesofcocoa.com/1")!

session.dataTaskWithURL(URL) { (data, _, _) in
  // handle response
}.resume()

We can even wire Kakapo up to Alamofire (Bite #93) like this:

let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.protocolClasses = [KakapoServer.self]
let manager = Manager(configuration: configuration)

This barely scratches the surface of what Kakapo has to offer.

From advanced dynamic mocking and database functionality, great routing, and a squeaky clean API, it's definitely worth a look.

Learn more about Kakapo at git.io/kakapo

Weekly Sponsor: Buddybuild 🤖🛠

We've got one of our favorite sponsors back this week, it's buddybuild! Long time readers will remember that buddybuild is a fantastic mobile continuous integration, delivery, crash reporting and feedback platform, all in one.

It takes just minutes to set up, let's check it out!

We'll head over to buddybuild.com and click Get Started. We'll sign up with Github (we could also use Bitbucket or just an email/password).

Next, buddybuild will let us choose a git repo to create our first project with.

 

Once we select the repo we want to build, buddybuild will get to work building our app for the first time.

After that build is complete, our app is set up on buddybuild - it's that easy.

Now, we'll be able to trigger a new build (and run our tests with code coverage) at any time with a simple git push!

This works with repos on Github, BitBucket, GitLab or any other git server, neat!

 

With buddybuild, we won't need to wait for App Store processing time or reviews before deploying to testers.

Speaking of deployment, buddybuild's email (and Slack!) based deployment service can deploy instantly on every build, every night, or at the push of a button.

Buddybuild's deployment service also handles the process of adding new users (and their devices) by automatically managing UDIDs, iOS provisioning profiles and signing identities. (Fantastic UX for both testers and devs!)

 

Only buddybuild goes even farther, and gives us a fully integrated feedback platform. Once users have installed our app and are testing it out, they can send their feedback (along with important diagnostic details) by simply taking a screenshot.

If our app ever crashes, buddybuild will trace back and highlight the exact line of offending source code that caused the crash, telling us which users were affected, and how many times the crash happened.

Each crash is also recorded with an Instant Replay - to show you exactly what your users were doing in the moments leading up to the crash. Awesome!

Buddybuild is also a great community citizen, and has our backs as iOS developers. For example, they'll give us a heads up on any potential breaking changes in Xcode. Within 48 hours of any Xcode release (including betas!), buddybuild will automatically takes our most recent successful build, and build and run tests against it using the latest version of Xcode. Then it will email us the results. How cool is that?!

Last but certainly not least, buddybuild comes with built-in integrations with tons of services we all know and love such as GitHub, BitBucket, GitLab, Slack, JIRA Pivotal Tracker, Slack, HipChat and more!

Buddybuild is the real deal, give them a try today at buddybuild.com!

Today we'll look at a new library from Krzysztof Zabłocki called KZFileWatchers. It allows us to easily monitor local and remote files, running code when changes occur. Let's dive in.

Watching files for changes is a common technique used when creating "live" updating interfaces.

This is a popular technique among web developers. For example, it's now common to use a tool to "live reload" a web page whenever a CSS file is changed.

Live updating techniques can dramatically change how we work, allowing us to try out changes more rapidly.

KZFileWatchers helps us build this type of functionality by providing two simple tools:

FileWatcher.Local is for observing local file changes. (It can even cross sandbox boundaries for debug simulator builds, think "config files on the desktop").

FileWatcher.Remote is for observe remote file changes. We can place a file on a server somewhere, and KZFileWatchers will use the Etag headers and Last-Modified-Date. This even works with Dropbox. Neat.

Let's use a FileWatcher.Local to make a live updating label.

First we'll create a label:

let textLabel = UILabel()

Then we'll create our file if it doesn't already exist:

let filename = "label-content.txt"
let middle = FileWatcher.Local.simulatorOwnerUsername()
let path = "/Users/\(middle)/Desktop/\(filename)"

if FileManager.default.fileExists(atPath: path) == false {
  try! "Hello, world."
    .data(using: String.Encoding.utf8)?
    .write(to: NSURL.fileURL(withPath: path))
}

Finally, we'll wire up a watcher to our file's path, and update our label when the file changes:

let watcher = FileWatcher.Local(path: path)

try! watcher?.start {
  switch $0 {
  case .updated(let data):
    textLabel.text = String(
      data: data,
      encoding: String.Encoding.utf8
    )
  default: break
  }
}

We can use this technique to drive all sorts of systems. With this we can easily enable/disable features, change content of labels in our UI, or build a full fledged theming system that updates in "real time".

More info about KZFileWatchers can be found at git.io/filewatchers

Today we'll take our first step towards contributing to the Swift language. We'll learn how to download the codebase, compile it, and run tests. Let's get started!

First, we'll prepare our environment. We'll be doing all of this on a Mac today, but all of this is also possible on Linux (and a bunch of other platforms).

We'll begin by using homebrew to install a couple of build tools:

brew install cmake ninja

Once that's done, we'll make a new directory somewhere sensible where we can put everything:

mkdir -p ~/projects/swift

Next, we'll do the first clone:

git clone git@github.com:apple/swift.git

Once this is done, we'll pull down all the dependencies and other projects involved with building Swift:

./swift/utils/update-checkout --clone-with-ssh

We have now cloned and checked out a lot of code, it's time to get building. We'll head into the swift directory and kick off a standard build, then run basic tests like this:

cd swift
./utils/build-script -r -t

That's it! At this point we can go get a cup of coffee (no really, this is going to take a while, even on a fast machine).

With these skills in hand though, we can now edit code, and see what effects our changes have on tests.

We can run basic tests at anytime with:

./utils/build-script --test

Or run more intensive validation tests like this:

./utils/build-script --validation-test

This is just the beginning, in the future we'll look at fixing a Swift bug, and contributing our work back to the project.

We've got one of our favorite sponsors back this week, it's buddybuild! Long time readers will remember that buddybuild is a fantastic mobile continuous integration, delivery, crash reporting and feedback platform, all in one.

It takes just minutes to set up, let's check it out!

We'll head over to buddybuild.com and click Get Started. We'll sign up with Github (we could also use Bitbucket or just an email/password).

Next, buddybuild will let us choose a git repo to create our first project with.

 

Once we select the repo we want to build, buddybuild will get to work building our app for the first time.

After that build is complete, our app is set up on buddybuild - it's that easy.

Now, we'll be able to trigger a new build (and run our tests with code coverage) at any time with a simple git push!

This works with repos on Github, BitBucket, GitLab or any other git server, neat!

 

With buddybuild, we won't need to wait for App Store processing time or reviews before deploying to testers.

Speaking of deployment, buddybuild's email (and Slack!) based deployment service can deploy instantly on every build, every night, or at the push of a button.

Buddybuild's deployment service also handles the process of adding new users (and their devices) by automatically managing UDIDs, iOS provisioning profiles and signing identities. (Fantastic UX for both testers and devs!)

 

Only buddybuild goes even farther, and gives us a fully integrated feedback platform. Once users have installed our app and are testing it out, they can send their feedback (along with important diagnostic details) by simply taking a screenshot.

If our app ever crashes, buddybuild will trace back and highlight the exact line of offending source code that caused the crash, telling us which users were affected, and how many times the crash happened.

Each crash is also recorded with an Instant Replay - to show you exactly what your users were doing in the moments leading up to the crash. Awesome!

Buddybuild is also a great community citizen, and has our backs as iOS developers. For example, they'll give us a heads up on any potential breaking changes in Xcode. Within 48 hours of any Xcode release (including betas!), buddybuild will automatically takes our most recent successful build, and build and run tests against it using the latest version of Xcode. Then it will email us the results. How cool is that?!

Last but certainly not least, buddybuild comes with built-in integrations with tons of services we all know and love such as GitHub, BitBucket, GitLab, Slack, JIRA Pivotal Tracker, Slack, HipChat and more!

Buddybuild is the real deal, give them a try today at buddybuild.com!

When using UIImageViews, sometimes the built-in content modes can cramp our style.

Many times, we're displaying photos of people. In these cases, it'd be great if the image view could somehow be told to intelligently crop the photo around the person's face.

Today we'll check out a library from Beau Nouvelle called AspectFillFaceAware. It's super simple, let's take a look.

AspectFillFaceAware is essentially just an extension on UIImageView. It provides two ways to configure an image view to be "face aware".

The first is in Interface Builder, we can enable the feature by flipping on the feature in the Inspector. (Not seeing the option? Run your project once, then it should appear).

Here's the how it looks:

We can also enable the functionality in code by setting the image view's image using this new function:

imageView.set(image: avatar, focusOnFaces: true)

We can even throw a quick corner radius on the image view's layer to try out the "face aware" functionality on a circular view. (i.e. user avatars):

let radius = imageView.bounds.size.width / 2.0
imageView.layer.cornerRadius = radius

Under the hood, the library is using a low accuracy CIDetector with a type of CIDetectorTypeFace to handle the actual face detection. Want to dive deeper here? We covered CIDetectors way back in Bite #87.

More info about AsyncFillFaceAware can be found at git.io/faceaware

Topics

#250: Improvements to C APIs in Swift 3 🐤

Topics

We’ve covered a little about working with C APIs in Swift back in Bite #189. Swift 3 brings us a ton of new goodies and improvements around C APIs, let's dive right in and take a look.

Swift 3 improves upon a number of areas of C API usage in Swift, but the biggest one is importing functions as members. Essentially, taking free floating C functions, renaming them, and shoving them onto a type as functions.

One place where this behavior really shines is when using CoreGraphics to draw into a view.

Here's some basic drawing code in Swift 2:

guard let context: CGContext = UIGraphicsGetCurrentContext() else { return }

CGContextSetStrokeColorWithColor(context, UIColor.redColor().CGColor)
CGContextSetLineWidth(context, 2)
CGContextDrawPath(context, .Stroke)

In Swift 3, the code to do the same would be:

guard let context: CGContext = UIGraphicsGetCurrentContext() else { return }

context.strokeColor = UIColor.red().cgColor
context.lineWidth = 2
context.drawPath(mode: .Stroke)

The mechanisms powering this conversion under the hood are pretty neat. The full (now implemented) proposal can be found here, but here's a quick overview:

The first is a bit of automatic inference. Many APIs (like CoreGraphics and CoreFoundation) use consistent (albeit often verbose) naming schemes for their functions. The Swift compiler can now exploit this to (for example) detect functions returning a specific type and convert them into init functions in Swift.

So this C function would come in to Swift 2 like this:

func CGColorCreate(space: CGColorSpace?, _ components: UnsafePointer<CGFloat>) -> CGColor?

But in Swift 3 it's an init function:

extension CGColor {
  init?(space: CGColorSpace?, components: UnsafePointer<CGFloat>)
}

There's tons more of these automatic inferences for things like detecting getter/setter pairs of functions, converting Boolean functions into Bool properties, etc.

Finally, authors of C libraries can customize exactly how their functions are imported into Swift using the new swift_name macro.

Here's an example from the proposal that demonstrates how we can define which type our function gets imported on to.

struct Point3D rotatePoint3D(Point3D point, float radians)
__attribute__((swift_name("Point3D.rotate(self:radians:)")));

The string parameter we pass to swift_name has a bunch of little extra syntax to import things as inits, regular functions, getters/setters, etc.

As always when talking about Swift improvements, it's a good idea to check out the full proposal for more info.

Topics

#249: Enums in Swift 3 🐤

Topics

We've been looking at some the changes coming in Swift 3 recently in Bites #243 and #244. We'll continue our tour today by checking out what is new the world of Swift Enums. Let's dive right in.

We'll start with the obvious, in Swift 2 (and earlier) enums have been PascalCased. In Swift 3, they are camelCase.

Before:

enum PersonalityTrait {
  case Extraversion(multiplier: Float)
  case Agreeableness(multiplier: Float)
}

After:

enum PersonalityTrait {
  case extraversion(multiplier: Float)
  case agreeableness(multiplier: Float)
}

The Swift 3 migrator in Xcode 8 will prompt us to convert all of our enums to this new convention.

Additionally, all of Apple's frameworks have this new convention applied:

label.textAlignment = .right
label.baselineAdjustment = .alignCenters
label.lineBreakMode = .byWordWrapping

In Swift 2, there was some inconsistency about the requirements around when the "dot" in the "dot notation" was required.

In Swift 2, all of this was valid:

enum AdvertisementKind {
  case Small, Medium, Large, Giant

  func debugDescription() -> String {
    switch self {
      case Small: return "Small Ad"
      case .Medium: return "Medium Ad" // leading dot
    }

    if self == Large {
      return "Large Ad"
    }

    if self == .Giant {
      return "Giant Ad"
    }
  }
}

Note how enum cases are used interchangeable both with and without dots.

In Swift 3, this has been cleaned up and dots are now required when using this shorthand style to access enum cases. There's one exception and that is static functions on enums, which still infer self:

enum AdvertisementKind {
  case small, medium, large, giant

  static func randomKind() -> AdvertisementKind {
    return medium
  }

Watching Swift evolve in these ways is a great way to understand not just the syntactic structural changes being made, but also the reasoning and goals behind them. Those interested should definitely read over the proposal that prompted this change here.

The Swift language is always evolving. Bugs are being fixed, new proposals are implemented, etc. It'd be great if we could try out these features out as they're being implemented, without having to wait for official releases.

Today we'll take a look at how to download, install, and try out the latest Swift Toolchain in Xcode. Let's get started!

We'll begin by heading to https://swift.org/download/ and looking for the "Snapshots" section. Here we can also find many other preview releases, etc.

Click "Xcode" to download an installer:

We'll run open the installer, and complete its steps.

We can now open Xcode and select our new Toolchain.

We can also manage Toolchains in Xcode's preferences:

With our new Toolchain selected, all builds will use it, neat!

Getting involved with Swift's development is a great way to stay informed on where things are headed. We'll look at getting even more involved in future Bites!

Page 1 of 29