Designers: you can Objective-C, too!
How you can help your iOS engineer by getting into production storyboards and Objective-C — if they let you ;)
We just released a new version of the Potluck iOS app. It was an amazing 2-month sprint to build our first in-house app with only one iOS engineer. At Branch, designers code most of the front-end on the web app. As a result, it was a difficult transition to iOS because we were unable to contribute to the production codebase due to the difficulty of Objective-C. However, with our deadline fast approaching, I began to work with our iOS engineer, Alex, and take on the easier front-end projects.
From that sprint, I found four key ways for me to contribute:
- Styling the UI with storyboard style attributes (GUI)
- Laying out the UI with Auto Layout constraints (GUI)
- Implementing stock iOS functionality you get for free (code)
- Coding primarily front-end custom static views (code)
I’m definitely still a beginner and don’t understand a lot of the foundations of Objective-C, but if you find yourself to be in a position where you are able to help your engineer, it’s possible to jump in!
1. Styling the UI with storyboard style attributes
Redlining and speccing isn’t fun for either side. For the web, knowing how to code CSS means you don’t have to do that. The good news for iOS is: if your app uses storyboards, you don’t need to know how to code to help style the app.
What is a storyboard?
A storyboard is an optional part of iOS development, but if used, can allow non-coders to work on the app in Xcode. It’s very similar to other WYSIWIG mockup tools, and allows easy integration with code.
If you want to style the way an element looks, select it and switch to the Attributes Inspector:
For text labels, you’ll be able to change fonts (limited to system fonts for optimal rendering), colors, lines, alignments. Other elements may have things like background color and alpha. This is very similar to most mockup tools, and knowing how to use the Attributes Inspector properly and understanding its limitations will save a lot of pain when speccing your UI and type. Try poking around in the panel to see what you can change!
2. Laying out the UI with Auto Layout constraints
This is probably where you can help your engineer the most. With Auto Layout in the newer iOS SDKs, storyboard became much more useful for designers to layout the app UI. Redlined pixel values on iOS often don’t match your mocks, so I find it to be more efficient if I am able to jump in and set up the layout constraints myself without relying on the engineer.
What are constraints?
Think of them like a blueprint for how the elements of the UI will position themselves relative to each other and their containing superviews. You can set constraints for width, height, alignment, and spacing.
In CSS-land, they’d be the dimensional styles (width, height, margin) that help the elements know where to lay themselves out.
Here are three parts of layout constraints I find helpful:
Example 2.1: Adding new constraints
If you’ve positioned your elements correctly before adding constraints, Xcode is pretty good at generating the constraints you want, relative to the superview and the elements around it. Click those dotted red lines or use the dropdown menu to specify another element you want to constrain this element in relation to. In this case, I’m just adding the generated constraints to the containing superview of the “Label”: “Content View”.
You can edit and delete these constraints later in the Size Inspector.
Example 2.2: Right-click and drag to add relational constraints
Right-click and drag between two elements you want to add constraints between. If you hold shift while selecting constraints, you can add multiple at the same time. I’m adding left and right alignment constraints between the two “Label”s so that the secondary label is always aligned to the primary label. Note that I’m doing this instead of adding constraints to the containing superview “Content View” like I did for the primary label. Relational constraints will make the layout harder to break and grow more intelligently when sizes begin to change programatically.
Example 2.3: Pay attention to the yellow and red arrow for misplaced views and missing constraints
Often after you add constraints, Xcode will display a small yellow or red circle with an arrow next to the view controller in the Document Outline. Clicking this will reveal any misplaced views or missing constraints, which are very helpful for telling you what to fix so that the actual output when you build the app will match what you’re seeing in the storyboard.
Constraints can also help you deal with multiple screen size support. For example, if you set them up correctly to top and bottom layout guides, you can avoid relying on code to adjust iPhone layouts between 3.5" and 4" screens.
Storyboard style attributes and layout constraints are two great ways to help without getting into code. There are definitely parts of it that need to be mastered, as constraints can often conflict and it can be tricky to get the behavior you want (especially if your app supports multiple device dimensions and orientations). But when you start to combine constraints with code, you can even do animations and dynamic layouts that resize to content.
(Note: Xcode 5.1 is introducing a bunch of new ways to work with constraints from storyboard — I’ll write about that when it’s out!)
The following two ways, however, require some programming background:
3. Implement stock iOS functionality you get for free
Many apps now have custom views for the core parts, but there are many other parts that rely on more stock design patterns (e.g. simple UITableView for settings/profiles, UIWebViews for rarely-accessed but necessary things like legal text, or MFMailComposeViewController for presenting email dialogs). Apple’s own documentation and StackOverflow will help you implement many of these. If you’ve got any sort of coding experience, finding out what parts of your app can be implemented with stock iOS functionality can be a really helpful thing to do.
Example: Hooking up a UITableView cell to show an email dialogue
Let’s say you’ve set up a UITableView in storyboard with a bunch of cells in different sections. Now you’d like to hook up one of the cells so that when you hit “Send us feedback”, an email dialog appears.
First, create a new class in xCode (I named mine PLSettingsViewController and made it a subclass of UITableViewController because this is a pure table view). Then I assigned it using the Custom Class field in the inspector.
In order to attach code to the table view cells, Apple likes you to use their prescribed table view delegate methods.
Under the section “Managing Selections”, I see the method we want named -tableView:didSelectRowAtIndexPath:. This will be fired whenever a user selects a row in the table. To use any delegate method, we need to make sure that our class is a subclass of UITableViewController (as I did above) OR we manually declare the class’s conformance to the UITableViewDelegate protocol.
In order to identify which row was selected, we have to specify the indexPath we want to match. An indexPath refers to the “address” of the row, which goes by section # and row #. Looking at our storyboard, “Send us feedback” is in the 3rd section, in the 1st row (with the index path starting at 0). So when we implement this, it looks like:
One thing you’ll start to notice about Objective-C is that a lot of things are already written for you, but just need to be manually called. One example you’ll notice if you try to build the app now is that the row that you select is never deselected.
A quick Google for “table cell does not deselect iOS” will reveal that you didn’t call -deselectRowAtIndexPath:animated: at the end:
Popping an email dialogue
Now, if we want to pop an email dialog, a Google for “email compose dialogue iOS” will show that we need to utilize the MFMailComposeViewController. For this email dialogue, we also want to specify a recipient of “email@example.com”, and a subject of “Some feedback on Potluck”. The documentation shows we can also specify things like the body or attachments, too.
First, we should import the MessageUI headers at the top of the .m file, which will allow us to actually use the methods. The StackOverflow we Googled above used #import <MessageUI/MessageUI.h>, but here’s a shorthand:
Then, we’ll check to see if the user can actually send mail. If they can, we’ll set up the controller with the specifications we want and present (show) it:
Now if you try to build the app, the email dialogue will show.
But alas, when you hit Cancel or Send, the modal never goes away. Just like the table cell selection, this also needs to be manually coded. A quick Google for “dismiss mail compose view iOS” shows that we need the MFMailComposeViewControllerDelegate, as well as its method that is called when
We’ll dismiss the dialogue when that method is called:
…and before that actually starts to work, we’ll need to set the mail compose controller’s delegate to self:
Nice! Wasn’t that “easy”? I’ve realized that:
- Objective-C is really well documented. Googling will usually answer your questions.
- A lot of things need to be manually specified.
E.g. -deselectRowAtIndexPath:animated:, or manually dismissing the dialogue from within
- But most of those manual things are given to you for free, and you just need to autocomplete them. If they don’t autocomplete, you’ve either not imported the header files/set your protocol conformance properly/there’s a syntax error somewhere prior.
4. Implement primarily front-end custom static views
Most apps these days are relying less and less on stock iOS components, instead creating custom views, which are less Google-able. The good news is there are custom views of an app where it’s almost completely front-end that you can attempt to complete on your own (if not sitting by your engineer to ask questions). A good example is onboarding, where interactive walkthroughs and slideshows are fairly common. For Potluck, I ended up implementing most of the interactive onboarding with a combination of gesture recognizers and IBActions.
Example: Slide to start onboarding “cover”
I created a view in storyboard called “Intro cover” that I want to allow users to slide off to the left (past a certain threshold). In order to recognize the slide gesture, I’ll use the Pan Gesture Recognizer in storyboard and drag it to the “Intro cover”:
This will set up a recognizer on that view that I can now connect to code via an IBAction.
What is an IBAction?
An IBAction is a method you write in the .m file that you can later connect to a compatible storyboard element, such as a UIButton or Gesture Recognizer.
I’ll set up the IBAction in the .m file first:
Which will make it available in the Connections Inspector of the storyboard:
I want the user to be able to slide the introCover in sideways in the x dimension, but we’re using Auto Layout constraints on the cover! In order to access that constraint and change it, we’ll set up an IBOutlet.
What’s an IBOutlet?
Similar to an IBAction, an IBOutlet allows you to programmatically access elements in the storyboard.
Now we can go to the storyboard Connections Inspector and attach this IBOutlet to the constraint:
Now that I’m able to programmatically change the X position of the Intro cover, I can go back to the Pan Gesture Recognizer. I want the user to only be able to drag to the left, and if they let go past a certain threshold (80pts), completely animate the cover off the screen.
A UIPanGestureRecognizer is a subclass of UIGestureRecognizer, and it works where the method is called constantly as the user engages with the element that has the recognizer. UIGestureRecognizer has 5 primary interactive states: Recognized, Began, Changed, Ended, Cancelled (and two others: Possible and Failed). Based on the logic above, we need to write code for the Changed (drag) and Ended (let go) states. Take a look at the code I commented below:
Get to know animateWithDuration:…
One thing of interest that designers getting into Objective-C should definitely get into is UIView’s handy -animateWithDuration:… methods that easily animate any compatible properties (e.g. alpha, backgroundColor, center…). It’ll give you a lot of power when designing simple animations without having to go through an engineer!
In this Pan Gesture Recognizer, I use a method for UIViews called layoutIfNeeded:, which works in conjunction with Auto Layout constraints that you set that tells the app to relayout the view with any constraints that have changed. In this case, I’ve changed the introXPosition NSConstraint. Putting layoutIfNeeded: inside animateWithDuration:… magically animates the changes I’ve made!
I am definitely still a beginner in Objective-C. It’s a complex language and without a foundational understanding, I’m just doing things like setting @property as nonatomic and strong because that’s what I’ve seen on StackOverflow. However, this experience was one of the most rewarding things I’ve done and really helped our small team move quickly through the build phase. I plan to get and read a book like the one from Big Nerd Ranch, and you should, too!
This article was in no way comprehensive — I’m just too new to Objective-C to really delve into some of the finer details. My hope is that I will have given you some confidence and some ideas of places to start in Xcode. Why not try talking to your iOS engineering and seeing if you can help in any of these ways?
What are other ways you’ve found yourself able to help engineers in iOS? Leave a note or tweet!