We spend a lot of our time in Xcode. It's a huge app with tons of different panels and views to explore.
Today we'll look at some of the most helpful keyboard shortcuts in Xcode and how they can help us navigate around Xcode's interface more quickly and efficiently. Let's dive in.
Xcode's keyboard shortcuts can be tricky to learn (there's quite a few), but they are actually very intuitive (and usually guessable).
We can open any of the panes in the navigator area with β1-7. We can toggle the whole navigator open and closed by pressing β0.
We can do the same with the utility area (right side) using ββ₯1-7 and ββ₯0.
We can focus in the filter bar of the current pane with ββ₯J.
We can toggle the debug area with ββ§Y, toggle breaking at breakpoints with βY. We can also pause/continue execute with ββY.
Code Signing. The very mention of certificates or provisioningprofiles can send chills up an iOS engineer's spine.
We've all been there. Just finished up a great first pass at a new feature, or finally ready to submit to the App Store and BAM! We're stopped in our tracks by a confusing error related to code signing.
Today's fastlane Friday is a big one. Yesterday, a new fastlane tool launched. It's called match, and it fixes code signing. Yes, really. Let's do this. π
Most iOS teams have separate code signing identities for each member. This means most iOS teams have tons of provisioning profiles, probably lots of duplicates, invalid ones, etc.
Adding new devices or renewing certificates can be a huge hassle, and only makes on boarding new team members slower.
With match, we can avoid these issues entirely. match allows us to share one single code signing identity across our development team.
We keep this single identity (and it's associated provision profiles) in one central location.
match automatically syncs our iOS keys and profiles using a simple git repository. It handles everything (i.e. creating certificates and profiles), while we retain complete control.
Let's setup match for a project. We'll start by creating a new Github repository to hold our certificates, profiles, etc.
We'll call it certificates and make absolutely sure it's set to be private!
Next, we'll go into our project's main directory and run:
match init
We'll be asked for the URL of the repository we created earlier, then a Matchfile will be created to hold a few settings.
Next we'll run:
match development
match will create a new certificate and provisioning profile, and store them in our Github repo. They'll all be encrypted using openssl! π
In the future, when we get a new machine for example, we will only need to run that one command to pull down everything and install it all locally. Incredible. Setting up new machines or team members has never been easier (or faster ππ¨)!
This is only a small taste of how helpful match can be! Check out the incredibly well done complete guide that covers everything from start to finish at codesigning.guide
Let's draw some strings! There's plenty of text-drawing capabilities in iOS and OS X, with full frameworks like Text Kit (or the lower-level Core Text) dedicated to the task. Today, we'll start looking at these capabilities by using Core Graphics and UIKit to draw a multiline string.
Sometimes we need to draw text ourselves, βmanuallyβ. This can be helpful when optimizing for scrolling performance, or when complete customization is necessary.
First we'll need a view to draw into, we'll make a new UIView, and override drawRect.
Next, we'll start implementing our drawRectfunction with a few variables. We'll choose a font, then setup a paragraph style to make our text multiline, with some tall lines.
We'll also setup some drawing options to tell the system we want multiline text:
Attributed strings are a fantastic way to work with styled text on iOS and OS X. NSAttributedString is an incredibly full-featured API, but because of this, simple tasks sometimes require a fair amount of boilerplate code. Today we'll look at BonMot, a library from Raizlabs that simplifies the process of composing attributed strings.
BonMot takes the form of a set of chainable functions that we can use to compose attributed strings:
letfancyQuote="Traveling through hyperspace ain't"+"like dusting crops, farm boy.\n"+" β Han Solo"quoteLabel.attributedText=BONChain().fontNameAndSize("AmericanTypewriter",17.0).lineHeightMultiple(1.8).string(fancyQuote).attributedString
BonMot will do all the heavy lifting of applying attributes and return a fully-formed NSAttributedString ready for use wherever we need.
We can use BonMot to concatenate multiple composed attributed strings:
BonMot even supports the NSTextAttachment parts of the NSAttributedString API. We can generate an βimage next to a labelβ like this:
chain.appendLink(BONChain().image(ackbar))chain.appendLink(BONChain().fontNameAndSize("Futura-MediumItalic",17.0).string("It's a trap!"),separator:" ")
We've only scratched the surface here, BonMot has a ton of features to offer. More info about BonMot can be found at git.io/bonmot
Today we're looking at SwiftyBeaver, a library from Sebastian Kreutzberger that aims to improve Xcode's logging capabilities. Let's dive in.
After adding the library to our project we'll need to import the library in our AppDelegate. We'll also need to create a global log reference we can use throughout our app:
importSwiftyBeaverletlog=SwiftyBeaver.self
Then we'll need to tell SwiftyBeaver to log somewhere, let's set it up to log to Xcode's console and a log file:
SwiftyBeaver is built around the concept of "destinations". Here we're adding one for the Xcode console, then another to log to a file in our app's documents directory.
Now, we can use our global log reference to log messages. There's functions for each of the different levels. Each will log its level in its own color:
log.verbose("Nothing really happened")// graylog.debug("A thing happened")// bluelog.info("A good thing happened")// greenlog.warning("A probably bad thing happened")// yellowlog.error("A definitely bad thing happened")// red
Both built-in destinations have a ton of configuration options allowing us to customize how we'd like our logs to behave. We can customize the format of log statements or change a file destination's location, we can even define our own destinations if needed!
App Transport Security was introduced with iOS 9 and OS X 10.11. It aims to make the network calls we make from our apps more secure by enabling many best practices like TLS 1.2 and forward secrecy by default. Today we'll take a closer look, and learn how to disable it if needed.
App Transport Security makes support for Transport Layer Security 1.2 and forward secrecymandatory. It also requires certificates to have a SHA256+, ECC256+, or RSA2048+ signature. Don't worry if that sounds like gibberish, the idea here is that Apple will maintain ATS on an ongoing basis, keeping it always up-to-date with the latest security best practices and standards.
Apple is enforcing ATS by automatically "opting-in" the NSURLConnection, NSURLSession, and CFURL APIs (plus anything built on top of them).
This means these APIs will throw errors, and the connections will fail if we try to use them with a connection that doesn't meet all the requirements.
Unfortunately, not all connections we need to make in our apps will support ATS. In these cases, we'll need to tell the system to exempt these connections, and allow them to be made insecurely. We'll do this by adding some keys to our app's Info.plist:
We'll start by opening our Project's settings, then heading to the Info tab.
Then, we'll right click the list of keys, and choose Add Row. We'll use the inline plus buttons to continue adding and configuring rows until we end up with this:
There's also keys for allowing for lower minimum TLS versions, as well as not requiring forward secrecy.
It's encouraging to see Apple putting such an emphasis on securing our apps. App Transport Security is big step forward in making all of our apps safer for us and our users.
A giant continued thanks to Dringend for sponsoring this week's bites!
Dringend is an app for iPhone and iPad that allows us to create, develop, and even run our apps right on our iOS devices. We've all dreamed about Xcode for iOS, and turns out it's already here, with Dringend. Let's take a look:
Dringend lets us build and run our apps directly on our iOS devices. We can see warnings/errors during builds, then run the app right on the same device we're editing its code on!
Dringend works with standard Objective-C and SwiftXcodeprojects. We can browse them, open files, and edit them. Just like in Xcode on the Mac. Let's step back a second to appreciate how cool this is. We've opened our Xcode project, built it, and run it, all on our iOS device!
Full git support is also included. Dringend let us push, pull, commit, switch branches and even has submodule support. Additionally, Dringend has full support for syncing projects we stored on Dropbox!
Last but certainly not least, Dringend has a full-featured code editor with syntax highlighting for Swift + Objective-C, full find/replace support, and even project-wide file search with regex support!
It's another fastlane Friday! Last week in Bite #135, we covered how to install and setup fastlane and an initial Fastfile. Today we'll look at how we can take our fastlane skills to the next level and customize our Fastfile using actions. Let's get started.
We briefly mentioned fastlaneactions in Bite #135. Let's start by taking a closer look at them.
Actions are essentially build "steps". fastlane organizes these build steps into sets called lanes. Each action is responsible for a very specific part of the lane's larger task.
Let's add an action to a lane:
lane:betadoincrement_build_numbersighgympilotend
By simply adding the increment_build_numberaction, we'll never need to manually bump our build number again!
We can install dependencies with actions like carthage and cocoapods. We can deploy with the pilot and deliveractions, or use hockey and crashlytics to upload to those services.
We can notify teammates with slack or archive each release with github_release.
We can even define lanes to bootstrap our dev environment using actions like install_xcode_plugin or dotgpg_environment.
We can "shell out" to a truly custom build script as well:
sh"./script.sh"
Simply put, actions are how to get the most out of fastlane. If we're doing something each time we build or deploy, there's a good chance a fastlane already has an action for it.
If not, we can make our own. Just like the Fastfile itself, actions are written in Ruby. We can generate a new one with:
fastlane new_action
Detailed documentation on all actions is available, and we can check out the full list of 120+ actions with:
One of the most useful parts of Xcode Playgrounds is the way they allow us to visualize our code. We can click the Quick Look button, or insert a preview directly into our code with the Show Result button in the Results sidebar:
We can add visual representations to the assistant timeline using XCPlayground's captureValue function (Bite #136).
This can be incredibly handy for spotting problems quickly:
Tons of system types are supported like CGPath, NSURLs, and even many of SpriteKit's classes. These are actually the same representations that can be seen if we Quick Look something while debugging in Xcode.
We can add these capabilities to our own custom types (for both debugging andPlaygrounds) by adding a function like this to them, returning a supported type:
This is great, but only works on types that inherit from NSObject and won't work for things like Swift structs. Also, even though we're adding this to our own type, we'll still need to return one of the built-in, Quick Look-able types supported by Xcode.
For more flexibility, let's look at XCPlayground'sXCPlaygroundLiveViewable protocol.
This will let us visualize our own types by returning a view or view controller that will be shown in the assistant timeline when we capture a value:
Now, we can set our current page'sliveView to a instance of Person directly, and we'll see our custom view controller appear in the assistant timeline. Neat!
We're continuing our look at Xcode Playgrounds today with CocoaPods. Let's see what it takes to import a CocoaPod into a Playground.
We'll begin by creating a new Xcode Project. Next, we'll head into our project's directory and run pod init to generate our Podfile. We'll open it up and configure it just as we usually would:
Then we'll run pod install to generate the Workspace file for our project and install our pods. We're almost done, next we need create a new Playground and add it to our project.
Finally, we need to add our Playground to our Podfile'slink_with directive (only its name, not the .playground extension):
link_with'Spaceships','scratch-pad'
We'll run pod install one more time and we're done. We can now import the pod we installed into our Playground and try it out. Neat!