Easy Way Out

Jordan Morgan
The Traveled iOS Developer’s Guide
8 min readMay 8, 2015

--

Extrapolating general iOS workflows for efficiency

A quick note — all of my future posts will be published on my dedicated website and this publication is no longer being updated. Thanks for reading!

It’s generally accepted that cheating or otherwise creating shortcuts is the mark of a lazy person, or at best one who isn’t willing to give it his or her best effort.

I am that person.

…which is why I became a developer. Developers have the luxury to cheat and cling to the “work smarter not harder” mentality. If work can be made more efficient or cut out entirely, it only serves to free up more valuable development time. This week, we’ll look at common problems relative to iOS development and how to quickly solve them.

The UIKeyboard + Covering Views

World hunger. Distant space travel. Heck, time travel.

These are all problems or great challenges that will be absolutely solved before iOS natively moves your user interface into a viewable area when the keyboard shows up.

When new Cocoa Touch developers begin their journey in iOS, they tend to assign first responder status early on in the process. Immediately after that, they proceed to google something like this:

“UILabel covered by UIKeyboard when it becomes first responder.”

They then weep when they realize there’s not an intuitive solution out of the box, or worse, they must manage a scroll view and retool their UI to support it.

But, IQKeyboardManager scoffs at such notions.

Here is all the code you need to automatically move text fields and labels out of harm’s way:

You see what I did there?

There is zero code required. All that’s (mostly) required is too simply include this resourceful library into a project and one can simply continue on. And that’s how it should be.

  • Keyboard covering the user interface — solved.

Managing Too Many Images

If image assets managed themselves as SQL behind the scenes (they are actually JSON), they would proudly proclaim their relationship status as one-to-way-too-freaking-many.

Images are perhaps a symptom of innovation, as the new iPhone 6+ beautifully displays it’s user interface at an insane resolution and ppi. Beauty is pain, though, as developers were bequeathed with yet another image to manage, the @3x image.

I’ll give Xcode a fair shake, xcassets makes managing these images relatively palatable. But that’s the problem — you have to manage another thing in your project. Though as fate would have it, late on an afternoon during a fair spring day, Kevin Cathey let developers in on a little secret that hasn’t been talked about in depth since.

Turns out Xcode can spit out .png images of all sizes from a vectorized pdf at build time. Simply include your PDF inside your image assets inside Xcode and select “Single Vector” under “Scale Factors”. Sit back and smile as you see the @1x, @2x, and @3x slots dissipate into nothingness only to be replaced with one single slot: universal.

The scale factor option needs to be set for a vectorized PDF to be registered.

Xcode will then select the appropriate image for you at run time based on the size of the device requirements. One might assume that it just scales the vector accordingly, but instead a selection is made from one of the raster images created.

Alert: here be dragons — this approach is not always a good idea. This isn’t true vector support, remember, all Xcode is doing is creating .png files at runtime and you certainly have no say in the matter.

There is also no backwards compatibility with this method, much like some of the new label automatic sizing functions in iOS 8. Adding to that list is autolayout constraints producing blurred images for the vector. Keep in mind, one is unable to choose a new size for the image once you go the vector route as well, contributing to the autolayout issues.

No matter:

  • Keyboard covering the user interface — solved.
  • Too many images to manage — solvedish.

Async Design Patterns

I’ll keep this short since I recently spoke at length over the matter. It’s known among a multitude of developers that iOS just beckons for async programming. Making multiple trips to the server is just one common reason to do that dance, and it’s one dance of many that you’ll likely take in terms of async programming.

Async programming can be syntactically scrambled, error prone, and unnecessarily coupled.

Promises were birthed to take on that challenge, and in iOS one can utilize PromiseKit to make the task simple. PromiseKit wraps up promises in a way that is clean, clear, and incredibly easy for the programmer.

I’ll just go ahead and steal some code from some other lame blog post to demonstrate:

[self userSessionInitiated].then(^{ 
return [ServerSide profilePics];
}).then(^(NSArray *pics){
self.pics = pics
[self.collectionView reloadData];
}).catch(^(NSError *error){
//Failwhale
});

And my favorite:

id firstName = [API getName:url] promise];
id userLocations = [API getLocations:url] promise];
[PMKPromise when:@[firstName, userLocations].then(^(NSArray *data){
//Handle data
}).catch(^
//Man down
});

Making round trips to the server has never been easier. PromiseKit’s docs include a lot of information to get started, should you become interested.

Know this — if you are not familiar with promises and how they can help you, rectifying that situation will yield you less future headaches.

Async, we can be friends again:

  • Keyboard covering the user interface — solved.
  • Too many images to manage — solvedish.
  • Async Design Patterns — solved.

Launch Images

Moving on to the more obvious yet hardly utilized.

It’s nothing short of baffling that developers in Cocoa Touch are unaware of the following trick. In fact, it’s not even a trick, it’s not even something coded up and starred all over github.

It’s something Apple just gave you, free of charge and included in the Xcode 6.

In iOS 7, I often got close to a release only to start thinking about the launch images (in true developer/not a designer fashion). Opening up the launch image reserved space in xcassets yields a sea of slots with which to place your images, and along with it, my excitement to get to the proverbial finish line.

Of course, Apple knew this was the bane of many a designer’s existence. Enter LaunchScreen.xib. This is a simple .xib file Xcode bundles into your project that will enable one to utilize auto layout to specify simple constraints to handle all launchs. This is typically accompanied by an image view within the xib, or a collection of components that provides the illusion of the project’s first presented view controller.

The launch .xib works much like any other .xib, save for a few caveats.

I love launch screens now. I just pop over to the app’s .plist file and enter in the .xib’s name for the “Launch screen interface file base name” key and I’m done. It takes five seconds to implement and then I never think about them again:

  • Keyboard covering the user interface — solved.
  • Too many images to manage — solvedish.
  • Async Design Patterns — solved.
  • Multiple Launch Images — solved.

The Art of the Universal App

This one is a passionate topic for me. I’ve written about it, leisurely talked about it, and am even doing a course at Pluralsight over it. But, much like the launchscreen.xib, it seems the community at large is either ill-versed on the matter or just aren’t fully aware of what adaptive design can do.

The bottom line is this, most of the time (not all of the time) it’s only going to help a developer to have their app be available in more places. In iOS, this implies a release targeting both the iPhone and iPad, commonly referred to as the universal app. That can intuitively be achieved via adaptive design.

Even if that weren’t a concern, there is simply no denying that developing between the two devices is quickly producing a blurred line — and that’s a good thing.

Size classes should be your new best friend. With them, one is able to develop in more abstract terms instead of thinking in black and white terms (i.e. this is for iPhone, this is for iPad).

Developers new to the topic tend to think that all components must go in the regular width regular height size class. That’s a mistake. What they must know is that it’s best to include as much as is reasonable in that configuration, and iterate down from there.

It’s not uncommon to still have those quirks or views that require their own special attention, and that’s fine. One can simply go down to a more specific size class and have those constraints and entire views only added to both that size class and its children.

Let’s look at some adaptive design benefits from a 10,000 foot view:

  • A unified story board
  • No reliance on device-specific logic
  • Shared components
  • Shared code
  • Flexible view controller presentation options
  • Appearance proxy support matching to size class
  • …ostensibly much more

Let’s just go out and say it, universal apps are the new single binary:

  • Keyboard covering the user interface — solved.
  • Too many images to manage — solvedish.
  • Async Design Patterns — solved.
  • Multiple Launch Images — solved.
  • Universal Apps — solved.

Small Gains In Readability

Readable code is a no brainer. The more one’s codebase turns into an amorphous blob of unusable trash, the less the business is able to do with the project going forward.

Swift’s property observers have produced some nice tweaks in my code that have made things flow across the eyes in a much smoother fashion. These modifications, though far from earth shattering, serve as simple enhancments. However, they seem to make all the difference when revisiting the source code weeks, months, or perhaps years from now.

Take our friend from UIKit that we’ve all had a dance with — the UIButton. Setting its text is accomplished easily. One specifies the text and the state:

aButton.setTitle(“Download The Halo Timer”, forState: .Normal)

Both are necessary, except that one parameter is almost always the same: .Normal.

Moreover, a lot buttons seem to find themselves as a property abstracted out into some view, table cell, or collection cell subclass. This makes my bones ache that much more, even though it’s blackboxed as it should be:

aSubclassedView.itsButton.setTitle(“Still download The Halo Timer”, forState: .Normal)

So, what can swift do for us? Simply add a convenience string property and utilize the didSet observer:

var buttonText:String{
didSet(buttonText){
aButton.setTitle(buttonText, forState: .Normal)
}
}

Presto. Now setting the text looks a lot more natural:

aSubclassedView.buttonText = “Visit bit.ly/halotimerios”

The same affordances can be extended to table or collection views. If the setup is elementary enough, one can automatically reload the view when the datasource changes:

var accounts:Array<Accounts>?{
didSet{
self.tableView.reloadData()
}
}
  • Keyboard covering the user interface — solved.
  • Too many images to manage — solvedish.
  • Async Design Patterns — solved.
  • Multiple Launch Images — solved.
  • Universal Apps — solved.
  • Some Gains In Readability — solved.

Final Thoughts

There are several other road blocks in iOS that are solved in very clever and unique ways. The mastery of the proposed technique shows itself when one knows which to employ for a given project — and even more importantly, when. Go forth and utilize these six methods as you see fit. Until next Saturday, friends.

Jordan Morgan is an iOS software engineer who runs Dreaming In Binary.
@jordanmorgan10.

If you learned something about iOS workflows, please NSRecommend this article below.

--

--

Jordan Morgan
The Traveled iOS Developer’s Guide

iOS @buffer. Author for Pluralsight, contributor to a few books, conference talks and some other stuff! Writing at swiftjectivec.com