We first looked at Swift's property observers back in Bite #179. They're a great way to know when a property's value is about to change, or just finished changing.
Kelan Champagne mentions an interesting technique for super-simple value-change tracking:
varpreviousStatuses=[String]()varawayMessage:String?=nil{willSet{guardletawayMessage=awayMessageelse{return}previousStatuses.append(awayMessage)}}awayMessage="out to lunch, brb"awayMessage="eating dinner"awayMessage="emo song lyrics"awayMessage=nilprint("Previous: ",previousStatuses)
This prints:
Previous: ["out to lunch, brb", "eating dinner", "emo song lyrics"]
This technique might not make sense in many situations, but is a nice feature to know about in case we can ever benefit from it.
UIPasteboard is a wonderfully simple little type with a ton of great functionality inside. (Covered previously in Bite #45). Today we'll check out the latest pasteboard improvements in iOS 10. Let's begin.
The biggest new user-facing feature of pasteboards in iOS 10 and macOS Sierra is the Universal Clipboard. This allows users to copy some content into their clipboard on one device, and retrieve it on another.
We don't need to do anything to get this functionality in our apps. This behavior is on by default for UIPasteboard.general, but we can configure how items behave when we add them.
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.
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 UIViewsubclass to show it off:
It'd be nice if we could still supply "one-off" UIColors as well. No problem, let's simply conform UIColoritself to be ColorConvertible. We can just return self:
lethv=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:
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:
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!
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:
lettextLabel=UILabel()
Then we'll create our file if it doesn't already exist:
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".
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 swiftdirectory 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!
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.
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'simage using this new function:
imageView.set(image:avatar,focusOnFaces:true)
We can even throw a quick corner radius on the image view'slayer to try out the "face aware" functionality on a circular view. (i.e. user avatars):
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
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.
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:
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.