Thanks to imgix for sponsoring this week's Bites! imgix is real-time image resizingas a service. They allows us to resize, crop, and process images on the fly, simply by changing their URLs. Let's take a look.
There's client libraries for all sorts of languages and environments, but for basic usage we don't even really need one. That's part of what makes imgix so awesome, we can play around with size, crops, effects, even draw text or watermarks on images just by changing some URL parameters.
They use our existing image storage locations as a source (supports public web folders, S3 buckets, and Web Proxies). We can configure multiple image sources, set caching times, and set custom domains on their site. Response times for images average around 70ms. 🚀
Let's look at using imgix in an iOS or OS X app. After signing up, we can use imgix's great Objective-C/Swift client library maintained by Sam Soffes. It's called imgix-objc (more info can be found at git.io/imgixobjc).
We'll create a client, and our first image URL. This will generate a signed image URL we can load anywhere.
Boom, say hello to Little Bites of Cocoa night mode. 🌃
Fun! A more realistic use case would be handling Retina displays. We can store our images' original size in full-resolution, then use imgix's awesome dpr parameter (plus a width and height) to serve up perfect, crisp images on any iOS device (or any display on just about any device for that matter).
Stop maintaining your frankenstein ImageMagick setup and let imgix handle it. It's totally free to get started. Use the link littlebitesofcocoa.com/imgix so they know you heard about them here. 👍
We've covered a few of the new 3D Touch APIs in iOS 9 like Static and Dynamic Shortcut Items (Bite #79, #88) as well as View Controller Previews (Bite #80), but today we'll look at how to access and utilize raw force values from a user's touches. Let's get started.
We'll start with the "Single View" template. We'll open up our Main.storyboard and drag a UIProgressView out to the top of the screen. Then we'll give it an @IBOutlet in our ViewController and wire it up.
Next, the fun part. We'll create a new function called updateForTouches, that will take in an optional Set of UITouch objects. We'll guard to make sure 3D Touch is available, and assume our force is 0.0 unless a touch is present. Then, we update the progress property of our progress view and for good measure, we'll set a red background color on our view, mapping it's opacity to the touch's force as well.
Lastly we'll need to implement all the touchesBegan, touchesMoves, touchesCancelled, and touchesEnded functions, calling our function and passing in the touches on each:
Success! If we build and run on an iPhone 6S or iPhone 6S Plus, we can start pressing the screen lightly and watch as the progress view and background color change as we begin pressing more firmly.
It might not be immediately obvious when playing around with Shortcut Items or View Controller Previews, but the hardware does in fact report every single tiny change in the force in real time. Neat!
Continuing where we left off in Bite #93 with our Alamofire Router, today we'll take a look at creating a Custom Response Serializer.
These are the mechanisms through which the Alamofire HTTP library translates the HTTP responses it receives into types that are more friendly to work with.
Alamofire ships with a few built-in serializers for common things like raw data, text, JSON and property lists. Today we'll be taking a look at adding our own. Let's get started.
We want to make it super easy to translate Alamofireresponses into structs that conform to the Decodableprotocol from the Decodable JSON parsing library. (Bite #86).
First we'll extend Request and add a new genericresponseCollectionfunction that returns a Response struct.
Notice that in the generic part of the function definition we allow any type T that confirms to the Decodable protocol.
Now the fun part. We'll first serialize the response using the built-in JSON response serializer, then switch on its result, returning the failure case if it exists.
If the JSON was parsed successfully, we'll try to decode using Decodable.
Now we can try both our Routerand our new custom response serializer out together:
The responseCollectionfunction handles arrays of objects. Making a responseObjectserializer function to handle single object responses is almost identical. Simply replace all occurrences of [T] with T.
Alamofire 3.0 will be released soon so now is a good time to start looking at how best to build an API client for our app. We'll be covering different areas of this topic periodically over the next few weeks.
Today we'll start by looking at one part of the equation: routing.
We've talked about routing before in the context of iOS URL schemes and libraries like JLRoutes (Bite #62). This is a bit different. We'll be creating a Router type that will help us unify and simplify our code when we make requests by generating URL requests from enum cases.
We'll start by declaring a new enum type that conforms to the URLRequestConvertableprotocol (which comes from Alamofire). Then we'll define a few different cases that each correspond to an endpoint on our HTTP API. We'll add a computed route property that returns a tuple to translate from our enum cases into URL path and parameter values.
Finally, we'll finish conforming to URLRequestCovertable by adding a computed property that encodes our URL and parameters into an NSMutableURLRequest. Neat.
Now we can use our new Router to write some super clean Alamofirerequest code like this:
Shared Links Extensions arrived with iOS 9 and OS X El Capitan this year. They allow our app to insert content into the users' Shared Links section of Safari on iOS or OS X. Let's add one to our fictional Little Bites of Cocoaapp so users can see all the latest Bites right inside Shared Links.
We'll start by going to File > New > Target... in Xcode and choosing a Shared Links Extension.
This will provide us with a new group in our project with one file inside, called RequestHandler.swift.
In this file there's one function called beginRequestWithExtensionContext(context:).
iOS will call this on our extension and that will be our cue to run whatever code we need to load the content we'd like to show in Shared Links, then return it in the form of an array of NSExtensionItems.
We'll return them via a completion function on the context we're passed in.
Universal Links arrived with iOS 9. Conceptually they're a way for us to logically tie the content in our app to the content on our website. Once this is done, iOS will be able to launch our app when a user taps a link somewhere, rather than opening our site in Safari. Let's take a further look by adding Universal Links to a fictional Little Bites of Cocoaapp. We'll start by registering and setting up SSL for our domain: littlebitesofcocoa.com.
Then, we'll head into Xcode and to the Capabilities tab of our project. We'll flip on the switch for Associated Domains, then click the + button and add our domain. Note that we prefix it with the phrase applinks:.
Now, our app will silently make an HTTP GET request to https://littlebitesofcocoa.com/apple-app-site-association.
It will expect us to return some JSON which describes our app's Bundle ID, and which paths should open it.
We'll open all paths on our domain using a wildcard character here, but we could easily, for example, limit to just Bite URLs.
After creating the file, we'll need to sign it so it is returned with a Content-Type of application/pkcs7-mime on our server. We'll use a command like the one shown here to sign the file. (This part stinks, but there's no way around it).
Lastly, we'll wire up the other side of the equation. When a user opens a Universal Link that iOS recognizes, it will call the same delegate function that's used to implement features like Handoff (Bite #29) and Spotlight Search (Bite #23). We'll check if it's a Universal Links activity type, then use JLRoutes (Bite #62) to open a section of our app.
Picking up where we left off in Bite #89: Today we'll look at adding our own custom project templates to Xcode. When Xcode 6 debuted at WWDC 14, one of the things that had seemingly gone missing was the "Empty Application" project template. This template was great because it made no assumptions about what kind of app or project we were creating. Let's add it back as a custom project template.
Much like we did when creating file templates, we'll begin by creating a folder for our custom templates to live in. This will be: ~/Library/Developer/Xcode/Templates/Project Templates/Custom. We'll create a new folder in here called Empty Application.xctemplate.
Then we'll need to create a TemplateInfo.plist to describe our template.
Most of this is boilerplate, except that last bit in TemplateInfo.plist, the Definitions dictionary. This where we'll specify the content of our base AppDelegate file. The full source of the Definitions block of the plistfile is shown below. Note how the key informs where to inject the code, and value contains the code itself.
<key>Definitions</key><dict><key>AppDelegate.swift:implementation:methods:applicationdidFinishLaunchingWithOptions:body</key><string>self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
// Override point for customization after application launch.
self.window!.backgroundColor = UIColor.whiteColor()</string><key>AppDelegate.swift:implementation:methods:applicationdidFinishLaunchingWithOptions:return</key><string>self.window!.makeKeyAndVisible()
return true
</string></dict>
Just like before we'll an icon for our new template. We'll add a TemplateIcon.tiff to our template folder. Now we can press ⌘N in Xcode to try out our new template.
Note: Keep in mind when using this template, that the UIWindow will need a root view controller set on it before our app can do anything useful.
The "Empty Application" project template we created in this bite can be downloaded here.
My continued thanks to the folks at Hired.com for sponsoring this week's bites.Finding a good job can be a daunting task. Today we'll take a look at how we can use Hired.com to save our sanity, and find a great job in the process. Let's dive in.
We'll start by entering our email and answering some basic questions:
That's it. Hired will then work with 2,500 pre-screened companies (both big and small) in 12 major metro areas to try find us a great job. Software engineers and designers on Hired can get 5+ job offers in a single week. Each offer will include salaryandequity details upfront.
If we get a job through Hired, they'll give us a $2,000 "thank you" bonus! If we use the link littlebitesofcocoa.com/hired to sign up, Hired will double that, giving us a $4,000 bonus when we accept a job!
More Reasons to Use Hired
🕒 Full time or contract opportunities are available.
✅ View offers and accept or reject them without talking to anyone.
😎 Completely FREE + no obligations ever.
Hired is the real deal. They have solved some very real problems and fixed this historically messy process. Looking for a job? Don't waste time, sign up for Hired today so you can get back to work! 💸
Xcode ships with some great starter templates for projects, files, and even targets. Today we'll look at how to add our own custom file templates to Xcode's built-in set. We'll be adding a new template for easily creating new table view controllers powered by Static (a static table view library we covered in Bite #74).
We'll begin by creating a folder for our custom templates to live in. This will be: ~/Library/Developer/Xcode/Templates/File Templates/Custom. We'll create a new folder in here called Static Table View Controller.xctemplate.
Then we'll need to create two files: One called TemplateInfo.plist to describe our new template, and another where our actual template content will live.
Let's start with TemplateInfo.plist. We'll create this using Xcode by selecting File > New > File... and then Resources > Property List. We'll call it TemplateInfo.plist (the name is important) and give it this content:
Then we'll select File > New > File... and select Source > Swift File. We'll name it __FILEBASENAME__.swift to match the value in our TemplateInfo.plist.
The template's content almost looks like normal Swift code, but contains template tags (which will get replaced and "filled in" at run time):
// Created by ___FULLUSERNAME___ on ___DATE___. ___COPYRIGHT___importUIKitimportStaticclass___FILEBASENAMEASIDENTIFIER___:TableViewController{overridefuncviewDidLoad(){super.viewDidLoad()dataSource.sections=[Section(rows:[Row(text:"Hello World")])]}}
Lastly, we'll add an icon for our new template by adding a TemplateIcon.png our templatefolder.
We can now press ⌘N in Xcode to see our new template. Success!
We covered Static Shortcut Items back in Bite #79, when 3D Touch was first introduced. Today we'll be taking a look at their close relative, Dynamic Shortcut Items. These offer the same behavior and functionality (allowing users to quickly jump to a particular section or feature of an app, straight from the home screen) but they can be configured and managed in code, and don't need to be defined in our Info.plist.
Dynamic Shortcut Items are particularly great for offering quick access to things such as user created content. Let's add a couple to our app. We'll use ours to let the user open recently viewed documents.
We'll create a function which we'll call whenever a document is opened in our app. It will update the current set of Dynamic Shortcut Items to match the 2 most recently opened documents.
We'll grab our recent documents, then define a new shortcut item for each one. We can handle tapping a Dynamic Shortcut Item just as we did in Bite #79, by passing a URL in the shortcut'suserInfoproperty then using JLRoutes (Bite #62) to route it correctly inside application(application:performActionForShortcutItem shortcutItem:completionHandler:).
Now both our static and Dynamic Shortcut Items are available by force pressing our app'sicon on the home screen.
Note: At publish time of this Bite, Xcode did not offer a way to test shortcut items in the Simulator. To generate the screenshot above (and test shortcut items' functionality) this project by Conrad Kramer was used.