Head First iPhone and iPad Development (2013)
Chapter 2. Basic iOS Patterns: Building from scratch
Now that you’ve gotten your feet wet, it’s time to start fresh. You should have a good idea of the tools you’ll be working with and how to get around Xcode a bit. Now it’s time to dig a little deeper and start your own project. How do you set up an iOS project, how do the pieces of the app really work together, and what are the interaction patterns you can count on? Turn the page, ‘cause you’re ready to find out...
iOS apps run full screen, but there’s a lot going on
One of the big things that separates working on an iOS device (i.e., an iPhone or iPad) from desktop or laptop computers is always working in full screen. In fact, when iPhone first came out, there wasn’t any multitasking on the device at all. That has changed, although it’s not multitasking in the sense that desktops do it. The user interacts with one app at a time through a particular view the app is showing on the screen.
Behind the scenes a view is splitting up responsibilities for responding to the user over a couple different pieces, as illustrated below.
Model-View-Controller is a design pattern
Model-view-controller (MVC) is a pattern that is discussed at length in Head First Design Patterns. You see it used a lot with GUI applications, and it’s all over the CocoaTouch framework. In MVC, we separate responsibilities into showing information to the user (the view), management of the underlying data (the model), and responding to interactions with the user (the controller).
NOTE
MVC is a standard design pattern and makes an appearance in a lot more than just iOS development. Ruby on Rails, for example, is loaded with it.
Breaking things up using the model-view-controller pattern helps keep the complexity down in your application and lets you reuse large parts of code regardless of the device you’re using (e.g., an iPhone versus an iPad).
WHO DOES WHAT
Match each MVC item to what it does in an iOS application.
Thing |
What the thing does |
Model |
The user interacts with this. It contains the buttons, images or other media, text, etc. that are being consumed by the user at any given time. |
View |
This is responsible for the data. It can be stored locally or in the cloud, use plists, databases, web services, etc. |
Controller |
This is responsible for coordinating responses to user interaction or things happening inside the application. Think of this as the traffic cop directing the flow of the application. |
WHO DOES WHAT SOLUTION
Match each MVC item to what it does in an iOS application.
THERE ARE NO DUMB QUESTIONS
Q: |
Q: Does every iOS app have a model, view, and controller? |
A: |
A: Yes and no. You’ll almost certainly have at least one view and corresponding view controller. Depending on your application, you might not have model backing things, but that will make for a pretty simple application. |
Q: |
Q: I don’t see anything called a model in the InstaTwit code. Does it not have one? |
A: |
A: One of the challenges with iOS code and a lot of the sample code is that it squashes model responsibilities with the controller. You end up with a gigantic ViewController that’s doing a little bit of everything. This becomes a maintenance nightmare. Can you see where InstaTwit has this problem? |
Q: |
Q: No... |
A: |
A: InstaTwit has the array of feelings and activities stored in the view controller. We did this on purpose to keep the code short in the first project, but if InstaTwit was a bigger project it would become a problem. Our later projects will be better about splitting that out. You’ve been warned. |
Marco needs a mobile social media app.
Fortunately, iOS makes Twitter and Facebook easy. It’s no secret that everyone assumes most restaurants will have some social media presence and a website. It’s also no secret that chefs are crazy busy and don’t have time to mess around. Here’s what Marco wants to be able to do with his app.
SHARPEN YOUR PENCIL
You have a rough idea of what the app needs to do. We’re only going to use one view; it needs to have a status update and it can post to Twitter. Sketch up what you think it should look like.
Get started with Xcode and Git
We’re on the road to professional iOS development here, so we’re going to set up a new project with Git enabled. As soon as we have the empty project ready to go, we can agree on a final design.
1. Create a new Xcode project.
When you launch Xcode, on the welcome screen “Create a new Xcode project” is an option, front and center. If you already have Xcode started, select File→New→Project...
2. Select a Single View Application.
Then click Next.
3. Select the options for the new project.
Set the product name as “MarcoPollo” and leave the Class Prefix as the default. Select iPhone as the device and click Next.
4. Select where you want to save the app. Make sure the Source Control box is checked!
The checkbox for “Create git repository on My Mac” is on this dialog. Make sure it’s checked before you click Create.
SHARPEN YOUR PENCIL SOLUTION
Here’s what we came up with for the final design for Marco’s app. It needs to have space for status updates and a way to publish those updates.
THERE ARE NO DUMB QUESTIONS
Q: |
Q: I came up with a different design. Is that OK? |
A: |
A: Sure! There are lots of different ways to design these things. If you go looking at similar apps up on the App Store (Hootsuite, Seezmic, even the Facebook App), you’ll see similar designs. Now that the App Store has matured, it’s always a good idea to look at apps that are accomplishing similar tasks to yours to get a sense of good designs. |
Q: |
Q: Do you really always start with design? |
A: |
A: User interaction on a small, mobile device is critical. It’s really hard to get it right the first time. As you get feedback from users and add features, your designs will evolve. Figure out what’s absolutely necessary, get rid of everything else, and build from there. |
Q: |
Q: Should we limit the length of text in the text box? |
A: |
A: Yes! Twitter only allows 140 characters. We’ll add a check in for that later. It’s definitely worth noting in the design comps though. |
Design time!
Now it’s time to get in Xcode and start building this view. Xcode has a really nice editor for GUI work: to edit the view, all you have to do is click the Main. storyboard file.
Xcode has a lot of configuration options.
To expose the different libraries on the side pane, you’ll need to click on these buttons in the upper-right corner of the view. There’s also a bottom panel for console output and other messages.
To configure what’s shown on the side pane, click these buttons here. Turn the page and we’ll show you the details.
DO THIS!
To edit the views in Xcode, you’ll need to open up the .storyboard file and change some settings in the workspace.
1. Highlight the Main.storyboard file.
2. Show the library by opening the Utilities Pane, here.
3. Show the Objects Library for the views by clicking on this button.
4. Adjust the size of the library by dragging this bar up.
Design time...redux
Storyboards were new with iOS 5 and provide an easier way for editing iOS UI. There is a drag-and-drop interface for the components themselves, which is a great way to speed up layout, but as your apps grow to more than one view, the transitions and flow between the views are also represented here. Since we already have a good idea of how the view will look, it’s a matter of dragging and dropping the pieces into place.
Let’s get started!
STORYBOARD CONSTRUCTION
We’ll go through each view component to add and configure them. We’ll start with the UILabel at the top of the view.
Grab a label and drag it into the upper-left corner of the view. When you do that, you’ll see some constraints pop up under the view controller. These guidelines are based on Apple’s Human Interface Guidelines (HIG) spacing recommendations and, in general, you should respect them and leave the recommended space.
Next, change the text of the label and fix the height. All of this work can be done in the Attributes Inspector on the righthand side of the editor.
We need to do similar configurations for the other two elements of the view, the UITextView and the UIButton.
Finally, just add the button to the bottom of the view, making sure that the default spacing from the edges stays in place.
TEST DRIVE
1. Here’s your storyboard in Xcode.
Right now you should have three elements: the label at the top of the screen, the text field for the post, and the button to complete the action.
We used Interface Builder to tweak some of the layout and fix some control heights to get things where we want them.
2. Click run. Here’s what’s in your simulator!
It should look just like what you have in your .storyboard file.
The stock controls are...stock controls.
Out of the box, the stock controls aren’t very exciting. There are lots of knobs we can twist, though, to spruce up our application. Most controls support custom images as well, so you can theme your application with color, button styles, etc. Be deliberate when you style controls—usability is critical, and while you might think a blinking neon green button is the shizzle, your users might not.
BRAIN BARBELL
Write up a list of your to-dos to handle Marco’s requirements. Check them at the bottom of the page.
1. Adjust the font for the title. 2. Remove the Latin and replace with default text that says “<your message here>.” 3. Change the text of the button to say “Post it!”
Cosmetic changes are easy in Xcode
We’ve used the inspector a little bit so far, but let’s get into some more details. First, we’ll fix the default text and the labels.
DO THIS!
Selecting the button, use the attributes inspector to change the text of the button to “Post it!”
Then select the text view, in the attributes inspector, delete the giant block of Latin text and replace it with “<your message here>.”
You could code this if you’re into that kind of thing...
When you make changes like font size or default text in Interface Builder, Xcode is storying that information in the storyboard so that it’s set when the storyboard is loaded by your application. Everything it’s doing, and even more, can be done in code in your application instead. Whether you make UI changes in code or through Interface Builder is somewhat a matter of personal preference and obviously depends on whether Interface Builder exposes what you want to change.
iOS controls are more than skin deep
We changed the button to say what we want, but it still doesn’t do anything when the user taps it. We need to wire that button up to some code to get it to do anything meaningful.
The code your button calls is an Action
If you think back to the MVC pattern we discussed earlier, we’ve just spent lots of time on the V (view). Now we’re moving into the behavior, so it’s the C (controller) part of the pattern.
To associate behavior with a user action, Objective-C associates Events with IBActions. (The IB in IBAction stands for Interface Builder.) Each control has one or more Events that it fires in response to something happening to it, like a tap from the user. We can use Interface Builder (though this can be done in code too) to hook up a control’s Event to some block of code we’ll mark as an IBAction. When the user does something to trigger that event, iOS invokes our action and passes us information about what just happened. Let’s take a look at how to write that action.
GEEK BITS
Xcode has a mode called the assistant editor that can show you both parts of a class at once (.h and .m), or a view with its associated view controller. You can also use it to graphically link Events and IBActions. To turn on that editor, you’ll need to close the righthand pane of the editor and turn on the assistant editor.
WATCH IT!
The Assistant Editor doesn’t always grab what you need.
If you see the .m file on the righthand pane, then click the arrows in the upper-right corner, here, to make sure ViewController.h is visible.
You’ll create the action using the Xcode GUI editor
The Xcode GUI editor lets you graphically set up the action for any component that needs it (in this case, the “Post it!” button).
1. Select the “Post it!” button in the storyboard.
2. Ctrl-click (or use the right mouse button) and drag over to the ViewController.h file on the righthand pane, landing between the @interface and the @end in that file.
3. Configure the connection as an Action named “postItButtonPressed.” To commit the connection, click Connect.
4. Xcode will add a declaration of the action in the header file and an empty implementation in the .m. Just to make sure it works, let’s update the implementation in the .m to log message to the action. Here’s the code:
TEST DRIVE
Connect your controls to your actions
This is your control
The control represents the view. It has visual information, font, text color, pressed and unpressed images, background colors, etc. It’s responsible for rendering some information to the user and collecting input back. Controls are used in all sorts of different places so rather than put application specific code in them, they simply fire off events saying “Hey! This just happened to me...”
This is your controller...
Application logic lives in the code you write in your application. But, by design, it’s a step removed from what the user sees. You don’t need to write code to draw a button for every app you write. You focus on behavior—what your application should do if the user wants to send out a message for Marco, for example.
Your control has events...
When we configured the connection in the dialog box in Xcode, there was a default event selected. If you go back in and click the drop-down box for that dialog, you can see all the different events a button can raise.
NOTE
You can only see all the options with a new event, not one that is already set up.
...and those events can connect to Actions
Different controls can raise different events, but, in general, events are raised to let the system know the user has done something. For example, we linked “Touch Up Inside” to our action so that we know when the user lifts their finger off the screen inside the button. You generally won’t use all of the events available on a control; 99% of the time you only need Touch Up Inside on a button, for example.
When you link an event to an action, iOS will pass along which control sent the event, which means you can use the same action for multiple events on different controls if you want to, as long as you check the sender. This can make your code a little more complicated than just using separate actions, though, so you usually just create an action for each event you want to respond to.
Linking Events to Actions is what ties user actions in your user interface to code in your application.
It’s coming along! You’ve got a control, an event, and an action. But there’s a lot more still to do....
1. Get the text that Marco types.
2. Add the marketing stuff to the text.
3. Tweet out Marco’s message.
4. Eat at Marco’s for free!
NOTE
Don’t worry if you don’t know what all of these mean! You’ll know in a few pages, but try this out!
WHAT DOES WHAT?
Match each thing from iOS development to what it does.
Thing |
What the thing does |
Control |
View element that can react to user interactions and raise events for anyone who cares to listen. |
IBAction |
An object that acts as the backing logic for an iOS view. This object typically has references to elements on in the view, code to respond to user interactions, and logic to transition to other views. |
IBOutlet |
An event that can be raised by a button to indicate that the user has lifted their finger inside the button—in other words, the button was tapped. |
View Controller |
An indicator on a class property that tells Interface Builder it should point to a UI control. |
Touch Up Inside |
Code (Objective-C) that is invoked in response to an associated Event being raised. |
THERE ARE NO DUMB QUESTIONS
Q: |
Q: I’ve heard of nib files. What are they? |
A: |
A: Before storyboard files, there were nibs, which are really .xib files. Those files now make up the .storyboard files and represent just one view. You can still work in specific nibs if you want, but for the purposes of this book we’re going to use the recommended Apple practice. |
Q: |
Q: What kind of files are .storyboard files? |
A: |
A: They are actually XML files. They contain information about how to draw the views and how to transition between them. As iOS development matured, it became clear that most apps support multiple views and that working between them was becoming a bigger and bigger pain point for developers. Storyboards are a great way to view the application as a whole and see exactly how your views are working together. |
Q: |
Q: This is our second app for iPhone, what about all the other devices? |
A: |
A: We’ll get there! For purposes of teaching, we’re keeping it simple for now. This is also a great opportunity to think about usability concerns. There are apps for which just an iPhone implementation makes sense. Running apps, transit apps, and anything that nobody is going to want to use on their iPad. |
Q: |
Q: What if I want to add iPad later? |
A: |
A: Good question. There are a couple of things that you can do. First off, you can choose the Universal app option, rather than iPhone only. We’ve also been taking care of something else in the views. Our view design hasn’t been fixed, we’ve been focusing on the spacing in the view. iOS development now has much more in common with web or even - gulp- Android development. With the iPad mini and the various Retina displays, there are a number of sizes to support and it’s only going to expand going forward. One way to insulate your application long term is to have the views based on spacing, not fixed locations. |
Q: |
Q: I really prefer the command line to GUI editors. What can I do? |
A: |
A: That works too. That being said, we really recommend you get over that. Apple has spent a lot of time and effort to improve the GUI editor and make it as useful as possible. Try to stick with it for a little while! |
Q: |
Q: You started talking about Actions. But we haven’t even talked about any syntax really... |
A: |
A: We’re getting there soon, we promise! Keep moving into the next page... |
WHAT DOES WHAT? SOLUTION
Match each thing from iOS development to what it does.
So about these classes and interfaces we keep writing...
We keep talking about View Controllers and User Interfaces, but we really haven’t spent much time talking about how classes and class interfaces work. We added a method (our IBAction) to our View Controller’s interface, but that’s about it. Let’s spend a couple minutes looking at classes in a little more detail. We’re going to spend the rest of the book writing them, so you may as well get comfortable...
CLASSES... UP CLOSE
Objective-C is loaded with Classes
Interface is what your class does.
NOTE
Your interface declares what your class can do and how it’s intended to be used by other objects.
Implementation is how your class does it.
NOTE
The implementation file is how your class does what your interface claims it can do. Other objects don’t care how you implement something, as long as they know you can do it!
Your code is written in classes. A class has an interface and an implementation.
Not really...
In Objective-C the .h simply declares the public interface of a class, including any properties, methods, and optionally any private ivars (though these you usually move into the .m and keep out of the public interface). A Java interface is often compared to an Objective-C protocol, which we’ll talk more about later.
THERE ARE NO DUMB QUESTIONS
Q: |
Q: Those events are kinda hard to understand? |
A: |
A: There are actually a ton of events that iOS can respond to for the different controls; the button is actually one of the easier ones. The words used to describe events are carefully chosen. “Touch up inside” is used because the iOS should be responding to the end of the button selection, the “click,” not the beginning. For more information about the events with descriptions, see the Event Handling Guide in the iOS Developer Documentation. |
Q: |
Q: I’m seeing compile errors? |
A: |
A: Well, that happens. Xcode is pretty good about warning you before you run the app. Some things you should look for in the top of the window: if you see little red exclamation points or yellow triangles, then you know something’s up. You can click on them anywhere you see them to get taken to the offending code, and once you’re there, to get an explanation of what Xcode is unhappy about. |
Q: |
Q: How do you hide or show the debugger? |
A: |
A: If the app stops while running in the simulator, you’ll dump right back into Xcode with the debugger view. To get back to the normal file navigation view, just click here: |
Q: |
Q: @ in front of strings? |
A: |
A: Remember that Objective-C is an object-oriented language. The string class commonly used in Objective-C is NSString and since strings are used all over the place, Objective-C provides a shorthand for initializing an NSString object: the ‘@’ symbol. |
So how do we get to that text?
Now that we have an action that will be called when the button is tapped, we need a way to access the text so that we can tweet it!
That’s right! In Objective-C, properties are used to access those variables.
Unlike other languages where you have to explicitly create your accessor methods, Objective-C properties let the compiler do the heavy lifting for you. All you need to do is define the property in your .h file.
Properties handle creating getters and setters
Using @property in the header file lets the compiler know we have a property. In modern Objective-C, these properties are automatically synthesized—you no longer need to write @synthesize in the implementation file. With a synthesized property, the compiler will generate a getter and, if it’s a read/write property, a setter, and implement it based on the @property attributes declared in the .h file.
Now, what does that all look like in Objective-C?
SHARPEN YOUR PENCIL
Of the code snippets below, only one will store the text view for the tweet. Circle the one that will work!
Create a property for that text field
We’ll need a property to wrap up everything for the tweet, and a way to get the information out. Using the storyboard editor again, we’ll create everything we need in one move to get the text set up and used in our app.
DO THIS!
Select the text field and then hit Control and drag over to between the @interface and @end of the ViewController.h file.
RELAX
We’ll do more property syntax later.
SHARPEN YOUR PENCIL SOLUTION
We gave you some options for which code snippet to use for the tweet. What did you come up with?
You connect your controls to outlets
Creating the outlet was the last piece so that we can interact with the text view. Since our text view stores the text for our tweet, we needed some way to access it in our code. In this case, we’re interacting with a control in our UI, not just responding to an event.
An IBOutlet references something in the UI
Since the user is interacting with the interface, we need a way to access and update that interface through code. In order to tweet, we need to respond to a button press (IBAction) and access the text the user has typed (IBOutlet).
TEST DRIVE
1. Connect to your outlet.
If you didn’t do this already, go back and Ctrl-drag in the storyboard to the ViewController.h file.
2. Log the message.
Once the outlet is set up, you have everything except a way to see that it’s working. Go ahead and edit the NSLog message in the postItButtonPressed method in the ViewController.m file like this:
3. Run the app in the simulator.
Build and run the app. Once it’s up and running, go ahead and replace the <your tweet here> text with something interesting and tap the “Post It” button...
THERE ARE NO DUMB QUESTIONS
Q: |
Q: What is an event again? |
A: |
A: UI controls trigger events when things happen to them. You can “wire” these events to methods so that your method is called when an event is triggered. Most of the time, you can wire events to methods using Interface Builder, but you can also do it in code (we’ll do this later in the book). |
Q: |
Q: So in one line of auto-generated code, we handle like eight things? |
A: |
A: Yes! Control+drag to create an Outlet in the storyboard editor gets you a line of code that starts with an @property, and so it declares the variable, creates the setter and the getter for the variable, and also has the outlet for the UI to get the text out of the text field. All in one tiny line of code. |
Q: |
Q: Didn’t there used to be @ synthesize? |
A: |
A: Yes, but not anymore. With the implementation of ARC (Automatic Reference Counting), Apple moved a lot of the memory management work involved in iOS development out of the code and into the compiler. The @synthesize was used to create the variable in the implementation file and start that process. Now the compiler handles all that for you. |
Q: |
Q: Does declaring an @property always generate a setter and getter? |
A: |
A: Not always! You can define a property to be read/write or read-only. When a property is defined as read-only, the compiler will only generate the getter. A read-only property ensures that a property can not be changed via a setter method. |
BULLET POINTS
§ Actions respond to events.
§ Outlets are used to work with the interface and present or receive information from the user.
§ The storyboard editor can be used to auto-create much of the code that you need to create Actions and Outlets.
§ Properties are used to create instance variables as well as the getters and setters for them.
Twitter, the easy way...
For the first time, iOS 6 gave you frameworks for talking to Twitter and Facebook. Instead of having to worry about figuring out both sites’ APIs and authentication, Apple is doing it for you—which is great, because these things change a bit.
NOTE
This is way easier—just ask your local Android Developer what a pain this is to do...
|
You’ll need to get the framework installed on your project to take care of messaging (frameworks are like libraries in Java). |
|
You’ll need to implement code within your app to fire off the tweet. |
READY BAKE FRAMEWORK
With the project highlighted, make sure the general tab is highlighted, then scroll down to the expand the Linked Frameworks and Libraries section, and push the + button. Then select Social Framework from the list and click Add.
READY BAKE CODE
Here’s the code that you need to add to make it all work. Just a few lines and you’ll be posting to Twitter!
Let’s try it out...
TEST DRIVE
1. Make sure you’ve added the Social framework and the ready bake code.
2. Build and run the app.
Go ahead and put a new tweet in for Marco.
3. Set up your Twitter account in the simulator.
When you hit “Post it!” you’ll be prompted to go into settings and set up your account. Once that’s done, these tweets will be live!
Nice work! Marco is gonna be overwhelmed with new clients...
THERE ARE NO DUMB QUESTIONS
Q: |
Q: So what’s the difference between an IBAction and a method? |
A: |
A: Nothing! An IBAction is no different than any other method in your implementation file. By declaring it an ‘IBAction’, the method is exposed to IB so you can wire it up to control events. |
#MarcoPollo
Marco wants his tweets to be postprocessed.
Marco is looking for efficiency and consistency. And also maybe some trending with #MarcoPollo. We need to add some more logic to the app so that it’ll add his hash tag...
IOS MAGNETS
We need to add the code to add Marco’s hashtag. Since that’s going to happen in the message formatting, it’s back into the action for the postItButtonPressed action again...
- (IBAction)postItButtonPressed:(id)sender {
NSLog(@"Post It button was pressed: %@", self.tweetTextView.text);
NSString = [ stringWithFormat:@" ", ];
____________
SLComposeViewController *composer = [SLComposeViewController compos
eViewControllerForServiceType:SLServiceTypeTwitter];
[composer setInitialText:tweetText];
[self presentViewController:composer animated:YES completion:nil];
}
IOS MAGNETS SOLUTION
We need to add the code to add Marco’s hashtag and check the post for 135 characters (for Twitter, Facebook doesn’t care).
TEST DRIVE
1. Enter the magnet code.
2. Build and run the app.
Go ahead, plug another tweet in there and my check it out! You’ll have a nice #MarcoPollo at the end.
3. Eat some chicken!
IOS BASICS CROSS
Let's work on some of that left brain now and check your terminology.
Across |
Down |
3. What your class does. 5. Something in a view that a user can interact with. 6. _________ files are used to design views. 9. ____________ is how your class does it. 12. Touch up _________ is usually used as a button click. |
1. Getters and setters make up _________. 2. The “C” in the MVC pattern. 4. An IB________ responds to an event. 7. The type of version control we’re using. 8. The “V” in the MVC pattern. 10. The “M” in the MVC pattern. 11. This basic pattern is used in iOS app design. |
Your iOS Basics toolbox
You’ve got Chapter 2 under your belt and now you’ve added some basic patterns and syntax to your toolbox.
BULLET PONINTS
§ Actions respond to events.
§ Outlets are used to work with the interface and present or receive information from the user.
§ The storyboard editor can be used to auto-create much of the code that you need to create Actions and Outlets.
§ Properties are used to create instance variables as well as the getters and setters for them.
IOS BASICS CROSS SOLUTION
Let's work on some of that left brain now and check your terminology.
Across |
Down |
3. What your class does [INTERFACE] 5. Something in a view that a user can interact with. [CONTROL] 6. _________ files are used to design views. [STORYBOARD] 9. ____________ is how your class does it. [IMPLEMENTATION] 12. Touch up _________ is usually used as a button click. [INSIDE] |
1. Getters and setters make up _________. [PROPERTIES] 2. The “C” in the MVC pattern [CONTROLLER] 4. An IB________ responds to an event. [ACTION] 7. The type of version control we’re using [GIT] 8. The “V” in the MVC pattern [VIEW] 10. The “M” in the MVC pattern [MODEL] 11. This basic pattern is used in iOS app design. [MVC] |