Active Filters: Tools

Today we'll dive back into the world of Xcode Source Editor Extensions (Bite #239). These extensions can not only help us save time and effort, they're also a great way to customize Xcode to our exact needs. Let's dive in! 🏊

First up, Cleaner Closures. We can use CleanClosureXcode from Patrick Balestra to clean up all those unnecessary ('s and )'s from our Swift closure definitions:

Beautiful. No more manually arrow-key-ing around to get rid of those.

Next, let's look at a common feature of many IDEs and text editors: the ability to "jump" the cursor multiple lines up or down. Xcode can't really do that... until now. Thanks to Jump, we're given a few new menu items in our Editor menu to move the cursor up or down by 2 or 5 lines. Neat.

Pro Tip: We can use the Key Bindings tab of Xcode's Preferences window to customize the keyboard shortcuts for each of these movement commands (or any other commands).

Finally, let's check out QuickAdd from Sidney de Koning.

This extension allows us to select some text, and then insert a new function definition into our code, complete with documentation comment, and placeholders we can press tab to jump between.

This allows us to employ a workflow of:

1.) Call a function that doesn't yet exist when writing some code as a sort of "placeholder".
2.) When we're done with that chunk of work, select the name portion of the function call and press a keyboard shortcut to "generate" the function and insert it into our file.
3.) Profit!

Full installation instructions are here.

Know of another neat Source Editor Extension? Send it along!

Topics

#283: Generating Models from JSON with json2swift βš’

Topics

Integrating our apps with HTTP APIs often involves a fair amount of "busy work". Writing models to match API responses, manually iterating each field in a JSON object, and typing each in as a Swift property can be a bummer. Today we'll check out a great new tool from Josh Smith called json2swift that can help us here. It can generate Swift model code from a JSON object. Let's give it a try.

After we've installed json2swift, we can run it like this:

json2swift Spaceship.json

This will create a new file called Spaceship.swift in the same directory as our .json.

This means if our Spaceship.json file looked like this:

{
  "name": "Tantive IV",
  "topSpeed": 950
}

The resulting json2swift-generated Swift model would look like this:

struct RootType: CreatableFromJSON {
  let name: String
  let topSpeed: Int
}

Neat!

json2swift has generated an immutable Swift struct from our JSON file. Pro Tip: We can also run this on a directory full of JSON files, and it will process all of them.

json2swift will even try to determine which properties should be optional, and which are required. It will then generate the appropriate init code.

We're even provided some special handling for things like Date parsing. If we put a special String like this in our original JSON:

{
  "name" : "Tantive IV".
  "buildDate" : "DATE_FORMAT=yyyy-MM-dd"
}

This will give us a:

let buildDate: Date

property, as well as generate the appropriate Date format/parsing code needed to make it work. Neat!

We've only scratched the surface, json2swift has great support for intelligenty inferring types for things like numbers, and even URLs. Learn more about json2swift at git.io/json2swift.

We touched briefly on this topic back in Bite #273 with Generating Initializers. Today we'll take a look at a few additional Xcode Source Editor Extensions (Bite #239) that can help us save time while working. Let's begin.

First up, Equatables. We can use XcodeEquatableGenerator from Serg Dort to quickly generate the long list of property comparisons often required when adopting the Equatable protocol in our Swift Structs or Classes:

Whew! That used to take ages! Full installation instructions are here.

Next, Localization. We've all been on a project with no localization. Adding that first round of NSLocalizedString() calls can be a pain. No longer! Now we can use Localizer from Esteban Torres.

With it, we can select a line of code like this:

let _ = "Mission Control Panel"

Then, when we run Localizer's command, this line becomes:

let _ = NSLocalizedString("Mission Control Panel", comment: "Mission Control Panel")

Neat! Learn more about Localizer here.

Last but definitely not least, is XcodeWay by Khoa Pham. This one is a bit different in that it doesn't modify or generate any code, but rather lets us quickly open a bunch of commonly used directories, by adding them to our Editor Menu:

Nice! No more hunting around in Finder or Terminal for these.

Know of another neat Source Editor Extension? Send it along!

Xcode Source Editor Extensions are really starting to come into their own. Today we'll look at one that solves an age-old annoyance for Xcode users: Importing.

We've all been there. We're deep down in the depths of file, and we realize we need to import a module. We dutifully scroll all the way up, type the import, then scroll back down trying to find our place, and get back in "the zone". Yuck.

Let's try out a new Source Editor Extension (Bite #239) from Marko Hlebar called Import.

As the name suggests, it allows us to type an import Module statement anywhere, then press a keyboard shortcut and have the import fly to the top where it belongs.

Let's try it out.

After installing the extension, we'll import CoreGraphics.

Xcode's Autocomplete still works here to help us find the module we want to import. Neat!

By default the keyboard shortcut is Command + Control + P. This trigger is also available via the menu item: Editor > Import > ☝️.

Success! Now we don't have to lose our place, or our train of thought when we need to import something.

Learn more about Import (including full installation instructions) at git.io/import

In some cases, Swift Initializers can be a pain to implement.

They can often be 100% boilerplate code, and feel like a chore to write.

This issue is at its worst when defining we're Swift Structs in a framework or module.

In Swift, Structs are automatically given a synthesised initialiser... with an internal modifier. Doh. 😣

This means the initializer is only accessible/visible inside the module we're defining it in.

This means we're stuck needing to manually add our own initializers for each of our Structs.

Creating and keeping these initializers up to date can add up to a ton of boilerplate code maintence. Yuck.

Today we'll try out an Xcode Source Editor Extension (Bite #239) from Bouke Haarsma that can help us write these automatically.

The extension works by taking the Swift properties defined within our selected text and converting them to parameters in a Swift Initializer.

After we install the extension, we can write up an example Struct in our code to try it out:

public struct Record {
  public let name: String
  public let type: UInt16
  public let unique: Bool
  public let ttl: UInt32
  var data: Data
}

We'll select just the properties, then select Editor > Generate Swift Initializer > Generate Swift Initializer.

Success! We just saved ourselves a ton of time, and typing. Neat!

Learn more about SwiftInitializerGenerator (including complete installation instructions) at git.io/swiftig

Xcode Project folders can be a messy place. Today we'll check out a tool from the folks at Venmo that can help us tidy up called Synx. Let's take a look.

At its core, Synx's main purpose is to reorganize the files and folders in our Xcode project folder to match the groups and structure we've setup inside Xcode's Navigator pane.

We can start by organizing a project full of content:

Then we'll install Synx:

gem install synx

Then we can simply head into our project's directory and run the main command:

synx ./OCMock.xcodeproj

Synx will work its magic and re-organize our files on disk, creating directories and moving files as needed to make things match the groups in our project.

Additionally, we can also use Synx to remove files no longer referenced in our project, like this:

synx --prune ./OCMock.xcodeproj

We're also provided a couple arguments to help us control how Synx behaves.

We can exclude files:

synx --exclusion /OCMockTests ./OCMock.xcodeproj

Last but not least, for those of us who like to manually sort our files by concept rather than name, we can disable sorting:

synx --no-sort-by-name ./OCMock.xcodeproj

Choosing how to organize projects can be a very subjective and personal choice, this is just one approach. Always use whatever works best.

Learn more about Synx at git.io/synx.

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.

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!

WWDC brought us a whirlwind of changes all over Apple's platforms. One interesting announcement was Xcode Source Editor Extensions. These allow us to add commands to Xcode that can work with the contents of the code we're working on. Yes, Apple also announced that Xcode won't load plugins (like Alcatraz, etc.) anymore. Bummer.

Today we'll try to shake off our feels about plugins going away by making our first Source Editor Extension, let's do it!

We're going to make a super-simple Extension that lets us easily "sign" our code comments. Like this:

// - @jakemarsh

We'll start by creating a new macOS app. Then we'll add a new target to it, and choose Xcode Source Editor Extension.

Xcode gives us a nice template of files to start with. We can head into SourceEditorCommand.swift to implement our command.

class SourceEditorCommand: NSObject, XCSourceEditorCommand {
  func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: (NSError?) -> Void ) -> Void {
    guard let selection = invocation.buffer.selections.firstObject as? XCSourceTextRange else { completionHandler(createError()); return }

    let commentText = "// - @\(NSUserName())"

    invocation.buffer.lines.insert(commentText, at: selection.end.line)

    completionHandler(nil)
  }
}

We start by looking at the invocation's selection and guard'ing to make sure there's a valid insertion point for us to append to, then create a new comment using the handy NSUserName() function in macOS.

Finally, we use the provided XCSourceEditorCommandInvocation one more time to insert the new comment text into the buffer. We call the completionHandler with a nil to let Xcode know we've completed our work without any errors, and we're done!

We can customize the name of our command in our Info.plist, like this:

Now, how are we going to test this thing out? Well, Xcode has some nice support built in for debugging these, but first we'll have to endure a little pain to get things working (at least during this first beta, later Xcode 8 releases will hopefully not need these steps).

We'll only need this while running OS X 10.11, macOS 10.12 users can skip this step:

We'll need to run sudo /usr/libexec/xpccachectl in Terminal, then reboot our Mac.

Once it's back up, we can open Xcode 8 again, and Build & Run our Extension. We'll be asked to choose which app we'd like to run it in. We'll choose Xcode 8 (be careful not to choose an older Xcode version as the icons are easy to miss).

Another instance of Xcode 8 will launch in our dock and… Boom! Xcode's dark heart is revealed!

Just kidding, Xcode is displaying itself this way to help us differentiate between the one that we're debugging, and the "real" one.

We can head to the Editor menu to test out our new command. That's not all though, we can go back to the other Xcode instance and set breakpoints, inspect variables, etc. Neat!

Plugins may be gone, but Source Editor Extensions still offer a ton of interesting possibilities. Looking for inspiration? Here's a few on Github already.

Plugins are a great way for us to extend Xcode, adding functionality that Apple didn't ship with it. We've covered Xcode plugins a bit here in the past, notably in Bite #147, where we learned about using Alcatraz to install plugins. Today we'll look at a new plugin called BuildTimeAnalyzer from Robert Gummesson. It can help uncover why are code is compiling slowly. Let's dive in.

We'll start by completing the steps in Bite #147 to install Alcatraz. (If we're going to be installing and trying out plugins Alcatraz is a good way to organize and manage everything).

Once installed, we'll open the Alcatraz Package Manager by going to Window > Package Manager.

We can search for "BuildTimeAnalyzer" in the search field to find the plugin and install it. Once installed, we'll restart Xcode and open our project.

We can open the analyzer window by selecting View > Build Time Analyzer from Xcode's menu.

Next, we'll need to add some compiler flags.

(Remember to add these to any other targets your app may depend to see compile times for those too).

We'll add -Xfrontend and -debug-time-function-bodies to the "Other Swift Flags" in our app's target's build settings.

After that, one last clean and build and we should start to see a list of how long each bit of our code is taking to compile. Neat!

We can click on each result to jump straight to the line of code that's causing the slow down. The results are often surprising!

For example: Adding Collection types together seems to bring the Swift compiler to a slow crawl.

What interesting slow downs did you find in your code? Send them to @lilbitesofcocoa on Twitter!

More info about BuildTimeAnalyzer can be found at git.io/bta

Page 1 of 5