the joe conway blog

People say I'm clever… sometimes. @joeconwaybnr

STKTableViewCell – Simplifying UITableViewCell

One thing that I see quite often is UITableViewCells that have a UIControl (like a UIButton or UISwitch) on them. In order to communicate which particular cell’s button was tapped, a programmer might set the tag property of the button to the row it appears on:

- (UITableViewCell *)tableView:(UITableViewCell *)tableView 
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    ButtonCell *c = ...;
    [[c button] setTag:[indexPath row]];
    [[c button] addTarget:self 
                   action:@selector(doStuff:) 
          forControlEvent:UIControlEventTouchUpInside];

    return c;
}

- (void)doStuff:(id)sender
{
    int row = [sender tag];
    // Do stuff with row 
}

Of course, in a sectioned table view, there needs to be an additional index, so I’ve seen some programmers use a bigger number to determine the tag:

[[c button] setTag:[indexPath section] * 1000 + [indexPath row]];

- (void)doStuff:(id)sender
{
    int section = [sender tag] / 1000;
    int row = [sender tag] % 1000;
}

This is a really brittle solution because it requires recalculation when you change the organization of the table view and it is very prone to error.

Therefore, I present you with STKTableViewCell.

STKTableViewCell simplifies using target-action pairs in UITableViewCells. It also makes creating instances of your cells a little bit more simple. Oh, and I also included a template for STKTableViewCells and a script to install that template into Xcode. All of this is located at https://github.com/joeconwaystk/STKTableViewCell.

Within this repository, you will find a sample project to show off STKTableViewCell. You will notice that there are two subclasses of STKTableViewCell – STKButtonCell and STKWidgetCell – as demonstrations of STKTableViewCell. STKViewController shows you how simple it is to integrate these subclasses into your application.

For your project, you will only need STKTableViewCell.h and STKTableViewCell.m. Drag these files into your project. The easiest way to create a subclass of STKTableViewCell is to use the template I’ve included in the repository.

To install the template, open the Terminal and run

./maketemplate.sh

from the STKTableViewCell root directory.

Now, a STKTableViewCell template will appear in the Cocoa Touch section of iOS in the New File… dialog. You can create your STKTableViewCell subclasses with or without a XIB file. If you choose to use a XIB file, simply drag all of your content views onto the cell in the XIB file and connect them to the instance of the cell in the outline view (not the File’s Owner).

If you choose not use use a XIB file, you may override the method cellDidLoad and layoutContent in your subclass implementation file:

- (void)cellDidLoad
{
    UIButton *b = ...;
    [b addTarget:self 
          action:@selector(buttonTapped:) 
forControlEvents:UIControlEventTouchUpInside];

    [[self contentView] addSubview:b];
    [self setButton:b];
}

- (void)layoutContent
{
    [[self button] setFrame:...];
}

Each control must send its action message to its cell. However, what we really want is for the controller of the table view to receive this message along with the index path of the control’s cell. In the cell’s implementation file, implement all action methods like so:

- (void)buttonTapped:(id)sender
{
   ROUTE(sender);
}

The ROUTE directive sends a message to the cell which forwards this message to the controller object. Each of your action methods will only ever ROUTE the sender.

In your table view’s controller, you instantiate STKTableViewCell subclasses like so:

- (UITableViewCell *)tableView:(UITableView *)tableView 
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   STKButtonCell *c = [STKButtonCell cellForTableView:tableView target:self];
   return c;
}

Note that +cellForTableView:target: will automatically create or reuse an STKButtonCell for you, as well as set up your controller to receive messages when the cell’s button is tapped.

Finally, in order for your controller to receive messages, you will implement a method in your controller’s implementation file that matches the selector of the control’s action message, plus the label atIndexPath:

// In your Controller.m

- (void)buttonTapped:(id)sender atIndexPath:(NSIndexPath *)ip
{
   NSLog(@"%@ was tapped in index path %@", sender, ip);
}

Make sure to include STKTableViewCell.h and .m in your projects!

You should feel guilty for over-sleeping; or, my generation is full of sissies.

I read this post on Hacker News today and I believe I’ve hit a breaking point on my opinion of my generation:

You all are lazy, crybaby complainers and I’m sick of listening to your excuses.

If you haven’t read the article above, I’ll summarize it for you: the author says he used to run late for meetings in the morning because he suffers from “Delayed Sleep Phase Syndrome”. He wants you to know that you shouldn’t feel guilty if you can’t get out of the bed in the morning to make a meeting, because you are the victim here. You were born with a disease. It’s not your fault.

Here is the deal: if you lack the decency to honor your responsibilities simply because you can’t summon the discipline to wake yourself up in the morning, you should feel guilty. If you think it is okay to make making members of your team – who work hard to show up on time – wait for you, consider this: your team members have a home and family life. They intentionally sacrifice a few minutes of time they actually enjoy with their family the night before the meeting so that the can get the required sleep to show up on time. When you run 10 minutes late, it moves their day back 10 minutes. That 10 minutes comes out of the time with their family.

You should feel 100% guilty for that. It’s your fault and your fault alone. Just because someone has conjured up a “label” for the way your brain works doesn’t give you a free pass to break your word.

No one likes waking up in the morning. It doesn’t make you special or unique, it means you lack the discipline to follow through with what you said you would do. Everyone else naturally wakes up earlier than you do? Boo-hoo, get off Reddit and go to bed earlier.

Everyone has their own challenges that are unique to them. Everyone gets their sleep schedule messed up sometimes. Everyone has gone through a break up. Everyone has lost someone in their lives. We have all had to struggle in some way against the hand we were dealt. Just today, it was reported that three kidnapped girls fought for 10 years to finally escape – and you can’t wake up 10 minutes earlier? What would they give for just 10 of your wasted minutes?

We used to value hard work. It was the cornerstone of our society. We invented computing, the telephone, the automobile and modern medicine. We invaded Normandy. We traveled to the moon. We dug our way out of every challenge that has come before us to get where we are now. Now we’re selling sepia filters for a billion dollars and complaining that we can’t pay our student loans back.

Gain some perspective. Every single one of your actions is controllable. Every outcome is influenceable. Refuse that last-place-participation medal that people want to give you and tell them, “You know what, I don’t deserve it, I didn’t earn a medal today.” Go back and put in the work. Earning your life is supposed to be difficult.

Useful macros for NSCoding

Remember the days where you had to implement the dealloc method for every class? Copying each instance variable from the header file and pasting it into dealloc was not only a pain the ass, it was a recipe for disaster. Forgot one instance variable? Memory leak. Had 30 or so instance variables for a class and accidentally released the same instance variable twice? Crash.

Fortunately, those days are over for memory management – but they still exist for archiving and unarchiving objects. How miserable is it writing the following code:

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super init];
    if(self) {
        _val = [aDecoder decodeIntForKey:@"_val"];
        _obj = [aDecoder decodeObjectForKey:@"_obj"];
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:_obj forKey:@"_obj"];
    [aCoder encodeInt:_val forKey:@"_val"];
}

Not only is this code miserable to type, but it is exceptionally prone to error: what happens if you misspell a key in one of the methods? Either you don’t save some piece of data or don’t reload it, both of which are errors that won’t make themselves obvious. Instead, some other part of your application will stop working and it will take a little bit of time to trace the issue back to a simple typo in your NSCoding methods.

There is a very simple solution, though, and it relies on a relatively unknown feature of the C preprocessor: stringification. In any C file, and therefore any Objective-C file, you can create a macro that contains the # character in front of a symbol. The macro turns that symbol into a C string (char *). For example, this:

#define STRINGIFY(x) #x
int myVariable = 5;
NSLog(@"%s", STRINGIFY(myVariable));

What’s that print? “myVariable”. Alright, what does this buy us?

Well, I can create another macro like this:

#define OBJC_STRINGIFY(x) @#x

Which means instead of getting a C string back, I get an NSString:

int myVariable = 5;
NSString *foo = OBJC_STRINGIFY(myVariable);
NSLog(@"%@", foo);

This, of course, prints out “myVariable” again. Why does this matter for NSCoding? Well, convention for encoding and decoding instance variables is to use the name of that instance variable as the key:

[aCoder encodeObject:_myInstanceVariable forKey:@"_myInstanceVariable"];

As you will notice, we are representing the same “string” in two ways in this line of code: once as a symbol for the compiler and once as an NSString. It would be much more simple and error-free to only write _myInstanceVariable once and have the compiler check it. With OBJC_STRINGIFY, that is easy:

#define OBJC_STRINGIFY(x) @#x
#define encodeObject(x) [aCoder encodeObject:x forKey:OBJC_STRINGIFY(x)]
#define decodeObject(x) x = [aDecoder decodeObjectForKey:OBJC_STRINGIFY(x)]

Now, your NSCoding methods can look like this:

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super init];
    if(self) {
        decodeObject(_obj);
    }
    return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
    encodeObject(_obj);
}

One of the things some folks don’t like about macros like this is that they can’t verify the code that is actually being written – false. With a .m file open, from the menubar, select Product -> Generate Output -> Preprocessed File. Xcode will generate what your implementation file looks like after all preprocessor directives have been evaluated.

Remember, though, that #import is a preprocessor directive. Therefore, a preprocessed .m file will contain every header file from Foundation, UIKit, and anything else you may have included – so be sure to scroll down to the bottom of the preprocessed result. (You may also notice that you can generate the assembly in a similar way, which is always interesting to check out.)

So, where do you define these macros like OBJC_STRINGIFY? Typically, I put them into a header file that has a lot of quick utility macros that I like to use in a lot of projects. Then, for each new project that I create, I import that header file into my pre-compiled header (the .pch file that comes with all of your projects). The pre-compiled header file for a project is transparently included in every file in a project. This means two things: anything in the .pch file is available in every file in your project and any time you change the .pch file you have to re-compile your entire project.

Now, back to NSCoding for a brief moment: remember that when archiving, you may not be encoding or decoding just objects. You may be encoding an integer, float or even a structure. So, you will probably need macros like this as well:

#define encodeFloat(x) [aCoder encodeFloat:x forKey:OBJC_STRINGIFY(x)]

For structures, I typically decompose each member of a structure during archiving anyhow, so if I were encoding a CGPoint, for example, it would look like this:

encodeFloat(_point.x);
encodeFloat(_point.y);

Of course, don’t take my word that this code works (even though it does), write it yourself and generate the preprocessed file to see the result.

A circular progress bar for iOS

Taking the red eye back from San Francisco is the bane of my existence, so I occupied the first hour of the flight creating this easy to use view and put it on GitHub. Bonus: other than the “profile image” area, everything else is drawn with CAShapeLayer. Have I mentioned I think CAShapeLayer is awesome? I should have.

It looks like this:
spinner

It can be found here. All you need is STKSpinnerView.h and STKSpinnerView.m, the rest of the crap is just a sample project to show it off.

Architecting Data Flow in an iOS Application, part 2

Make sure to read the first part of this topic here.

The overriding issue in developing an iOS application – or any client application – is that you have a very limited amount of disk space. And I’m not talking about the difference between a 32GB iPad and a 250GB desktop computer, I’m talking about the fact that the applications we really seem to care about have access to a seemingly infinite amount of data. An iOS application like Facebook, for example, has the ability to access so much data that it couldn’t ever fit on a single drive, much less your iPhone. (And, if you didn’t know and would like to be on the receiving end of a shameless plug, our team is responsible for training their mobile developers with the book I wrote.)

Therefore, the Facebook iOS application cannot possibly download and reconstruct the entire model graph that lives on Facebook’s servers. Which means that the concept I talk about in my last post – having a view controller hang onto the root model object and then chopping off its components to pass to other, more focused, view controllers – becomes more complicated.

In applications of this nature we must fetch data only as needed. For example, when I log in to Facebook, I send my username and password and get back data that identifies the appropriate user. However, this data is fairly limited: it doesn’t have all of the photos I’ve been tagged in or all of the user data that represents each of my friends. Instead, all I get back is some basic information like my name, maybe the school I went to (Go Badgers!) and most importantly, a unique identifier for this user data.

This, of course, is intentional. If logging in fetched all of a user’s photos and friends, then each one of those friend photos would be fetched, and all of their friends, and all of their friend’s photos, and so on, until finally we’ve moved the entirety of Facebook’s data onto to our iPhone. We’re all Kevin Bacon these days, apparently.

After fetching the user data, we would construct an Objective-C object that represents the User that is populated with the information we were given upon logging in, but that is the extent of our model object graph at this point. If we wanted to present the list of a User’s friends in a view controller, we are now faced with a problem: we don’t have a list of friends in memory.

Graph2

In a simple iOS application, the User object would have a pointer to an NSArray containing other User objects that represented each friend. The keyword here is “a pointer”, that is, direct access to friends. We don’t have that direct access to the friends here, instead, we have to call back out to the web server to grab that data before we can present it.

This problem is where the confusion sets and all kinds of wayward solutions creep up. When in reality, we are still in the exact same position as we were if all of the data was locally organized in a tree – even though it is remotely organized in a web. We still need to have a pointer to an array of friends in order to fit the architecture of our application (which is breaking off components of your model object graph to pass to controllers that operate on them).

If you know anything about Core Data, you know it solves a similar problem. Core Data uses SQLite to store its data, so it, like Facebook’s database, has a web-like object graph. When you fetch an object from Core Data, you don’t have a pointer to every object that it is connected to right away. Instead, the fetched object has pointers to faults.

For example, let’s say you fetched a User object from Core Data. Its friends property should point at an NSArray of other User objects, but instead, it points at a fault. A fault, here, is an object that knows the unique ID of the friends array in the database, but isn’t the friends array itself. This conserves the amount of memory we have loaded in the application, both because the fault itself is small and more importantly, because loading a list of friends would trigger loading their list of friends and so on.

When you access the friends property of the User object, the fault automatically goes back to the managed object context and replaces itself with the actual list of friends stored in Core Data (conceptually, at least; each friend is originally a fault, too). To us, this mechanism is transparent, but in understanding it, we can create the appropriate solution for our own applications that pull data from a web service.

Graph3

In the Facebook application, we call a web service that fetch a list of friends given a unique ID of a user. This is very much like a fault – we have the information necessary to get the friends, but we don’t have the friends yet. However, pulling data from a web server is a lot more involved than grabbing data from SQLite – it takes longer and may fail. Thus, we cannot obscure the fetch in a simple property access like Core Data does because things may not work or we would stall the main thread. We must be explicit about what we are asking for and handle any errors appropriately.

This is where Store objects come in. I’ve written extensively about Store objects in my book, but for those of you that haven’t read it: it is a singleton that creates model objects from data stored in an external source of data (like a web server or the filesystem) by request of controller objects. A method on a store that would fetch a list of friends would look like this:

- (void)fetchFriendsForUser:(User *)u 
                 completion:(void (^)(NSArray *friends, NSError *err))block;

A view controller that wants to display a list of friends would need a pointer to a User object. Thus, the view controller that has the User would pass it along to the FriendsViewController:

- (void)showFriendsList
{
     FriendsViewController *fvc = [[FriendsViewController alloc] initWithUser:[self user]];
     [self presentViewController:fvc animated:YES completion:nil];
}

The FriendsViewController, it would fetch the list of friends when it appeared:

- (void)viewWillAppear:(BOOL)animated
{
    [[FacebookStore store] fetchFriendsForUser:[self user] 
                                    completion:^(NSArray *friends, NSError *err) {
         if(!err)    
            [[self tableView] reloadData];
         else 
            [self showError:err];
    }];
}

The store would either fetch the list of friends for that user from the web server or use a cached list of friends. The store would then set the friends property of the User to the array of friends it received, and the FriendsViewController, having access to that user, would be able to display those friends:

- (int)tableView:(UITableView *)tv numberOfRowsInSection:(int)section
{
    return [[[self user] friends] count];
}

The beauty of this is that the Store made decisions about using cached/fresh data (or maybe it had already loaded the friends into RAM previously and did nothing), but according to our controller, we just have a tree of objects as we normally do. The only difference between this pattern and what I discussed in the last post is that controllers have a pointer to an object that is one level above the data that it is displaying if they need to fetch more data.

Graph1

Of course, if you want to drill down into the data any further – like look at a particular friend’s profile – you don’t necessarily need to know that this friend came from this user’s list of friends. Here, you can simply pass the friend object along.

We are still remaining consistent with passing only the necessary model objects to view controllers, even though we are passing more than we would if conditions were different. And, we are still using a tree of objects, even though the real object graph is a giant web. Just like some view controllers only see a subgraph of objects in an application’s model graph, an application only sees a subgraph of objects in a database’s model graph.

UserGraph

Now, I would be remiss if I didn’t mention that this pattern has some useful variations to it. For example, I like for the Store to hang onto the root model object, which is most cases, is the user object. That way, I don’t have to continue to pass the User object around, the Store always knows the current user.

Another variation of this is more closely models the concept of faults. Instead of passing the User to the FriendsViewController, I would pass a “fault” that represents the friends. Then, the FriendsViewController would not need access to the User – instead, that fault would essentially contain an empty array of friends and would have access to the User (it’s parent in the tree). When the FriendsViewController appeared, it would pass the “fault” to the Store, which would be able to unpack the necessary data to make the service request.

Architecting Data Flow in an iOS Application

One of the most important pieces to the Objective-C puzzle is realizing that most objects don’t really hold any data. Instead, they point to some other object that points to some other object which has actual data.

The majority of the time, classes like NSString contain – and data structures like bitmaps are – the only real data in an application. Sure, we have objects that represent a bigger things, like a Person or a Button, but these objects just contain references to real data. For example, a Person will have pointers to NSStrings that represent its name, phone number, etc.

The concept of a Person or a Button are just interesting formations of the same basic elements available in a computer, in the same way humans and trees are formations of the same elements available on earth.

But the real take-away here is that a Person isn’t just an object, it the root of an object graph. The idea of a “Person” object gives us a convenient way of addressing a collection of objects meant to represent something that we intrinsically understand in the real world.

This idea is why MVC is such a powerful architectural pattern for Objective-C: the same fundamental elements that make up a Button also make up a Person. We can extract one of these basic elements, like an NSString, from a Person and inject it into a Button. The same data can represent different things, depending on the formation around it.

Because of this, views don’t have to understand anything about a Person. Thus, we can reuse views like UIButtons and UILabels in any application, regardless of how the model objects are organized, because they are all made up of the same molecules. (Which reminds me for no particular reason, that if you haven’t see the movie Gattaca, your life is incomplete.)

I was recently asked by @htormey how to pass model objects between view controllers. And I think that what you’ve just read is necessary to understand the answer to this question.

While a Person is the root of an object graph made up of components that represent what a person is, a Person object can just be another component of some other object graph meant to represent something else, like a Company. A Company could hold many instances of a Person in an NSArray and alongside the array of Persons could be an array of Projects the company is working on.

In the same way we can break out an NSString component of a Person to display in a view, we can break out components of a Company into view controllers that know how to manage those particular components.

For example, in this theoretical application where there is a Company made up of Persons and Projects, there might be a view controller that can edit the contact information for a Person within that company. Does that view controller need to know about the Company that employs the Person to edit their contact information? No, in the same way that a view doesn’t need to know that an NSString came from a Person.

An object should only have access to the information it needs to know about to perform its job. In the case of a view object, this restriction of information is for reusability; the same button can exist in any application because it only deals with the fundamental objects available in all applications.

For view controllers, this restriction of information is for maintainability. For example, if you give a contact-editing view controller access to the whole company, you are opening yourself up for a problem.

One of the best possible ways to determine if your code is going to be difficult to maintain is to draw out an object graph of the important objects in your application and draw lines between objects for every pointer. Each line introduces a dependency. The more dependencies, the more code you will break when you make a change.

This problem typically doesn’t manifest itself right away. Instead, you give too much data access to a view controller because it is the easiest way to solve some problem quickly. Later on, someone else (like a co-worker) comes along and doesn’t realize that this view controller shouldn’t be accessing some data it does have access to, accesses it, and now you have dependencies. (Don’t work in a team? Still applies; you today is “someone else” than you 3 months from now as far as code is concerned.)

Thus, a controller should only have access to the subgraph of model objects that it is operating on. This means that a view controller that edits a Person’s contact info will have a property like this:

@property (nonatomic, strong) Person *editingPerson;

As far as that contact-editing view controller is concerned, the editingPerson is the root of the object graph in this application. It can’t see any higher than that, nor should it.

You end having a controller graph that somewhat resembles your model object graph, like so:
DataAccess

Of course, this all becomes a bit more fuzzy when you start talking about fetching things from web servers and the filesystem and when to save, but that is something I will talk about in another post soon.

iOS Autolayout: Fun Facts and Tips

Have you ever stared at the tracking information for your new MacBook, hitting refresh every 5 minutes? It is infuriating. But the fact that a MacBook can come off the assembly line somewhere in China and end up at my doorstep a few days later is a serious work of mathematical art.

Consider all of the issues in optimizing the pickup and delivery of your next MacBook: a company like FedEx has to factor in the number of trucks they have, the amount of goods that can fit on those trucks, the cost of gas, the distance from their nearest distribution center to your doorstep, and so on. If they were to just shoot from the hip and deliver things in whatever order their manager thinks is best, they would run out of money or your shiny laptop wouldn’t show up. Instead, they have to rely on a field of math called linear programming to determine the way they operate.

Linear programming (which has nothing to do at all with programming in the way we think of it, but instead, is a synonym for linear optimization for math folks) is used to solve equations for which there are a lot of variables that depend on each other. FedEx needs to minimize some of these variables (like the amount they spend on gas) and maximize some others (like how many items can be delivered in a day).

Because there are so many variables involved and each of their ranges is so vast, a human being couldn’t find the optimum value for each of the variables to minimize their costs and maximize their production, but a linear objective function can. A human being can set up some constraints for each variable, like a truck can travel up to 200 miles in a day and gas costs $3.50 today. Each of these constraints is a simple linear equation, like travel <= 200.0 and gas = 3.50. A linear objective function is a combination of all of these equations solved at once that finds the optimum value for each unsolved variable.

What does this have to do with autolayout? The autolayout system is one big linear objective function. Each NSLayoutConstraint you create is just one linear equation in a linear objective function. For example, one constraint could be view.left = anotherView.right + 10 and another could be view.width >= 20.

When a view is being laid out, the linear objective function is evaluated to determine a minimum and maximum value for each part of a view’s frame. A valid set of constraints for autolayout is when every variable has a maximum equal to its minimum; that is, there is only one solution to satisfy every constraint in a view hierarchy. (If there is more than one solution to the function, you have an ambiguous layout, if there isn’t a solution, you have conflicting constraints and you get an exception.)

Because of the way linear objective functions are evaluated, there isn’t an order that the constraints are computed in. So if that was how you were approaching constraints, get that out of your head: an equation like view.top = anotherView.bottom + 10 doesn’t mean that you find the value of anotherView’s bottom first and add 10 to get view’s top. It is just one more equation that has to be satisfied for your layout to work; both of these variables can change depending on the other constraints.

Of course, the math behind all of this is really complicated. The implementation of autolayout is less complicated, but let’s not pretend it is easy at first. So, here is what I recommend:

1. Use autolayout only when you need to

Autoresizing masks aren’t deprecated or obsolete. Just like Core Data didn’t make archiving obsolete nor did blocks make delegation useless, you will still use autoresizing masks. Many iOS applications – while they may have pretty artwork – are pretty simple layout wise. You have a table, it has some cells, there is some stuff in the cells, there are some buttons above it and maybe a duck. Well, probably not a duck, but do you really need autolayout to keep the table view on the bottom of the screen and the buttons as a header on top? Does a cell with two text fields need autolayout to keep them aligned with each other? Will rotating the device, putting into a navigation controller or running it on an iPhone 5 really change the layout of this view? No, so don’t overkill it with autolayout.

2. The keyboard shortcut you need to know about

Manipulating the layout of a user interface in a XIB is, let’s face it, a cruel joke. Once a view is dropped into a XIB, you get all kinds of constraints that make sense for the position of that view where you dropped it – but not where you eventually want it. On top of that, Xcode enforces the constraints that apply to your views when manipulating them in the XIB – got a label that is pinned to match the size of the button below it? Xcode may not let you drag the resizing controls for that label.

Unless you hold the command key. The most useful but under-documented feature of autolayout is holding the command key while manipulating views in a XIB file. While holding the command key, Xcode lets you break any constraint applied to a view while resizing it.

3. Stop thinking about frames

When laying out an interface, we typically think about the frame of a view. Stop. The frame of a view is an absolute position and size. That doesn’t make sense when a view should lay itself out relative to the rest of the screen. Want to think about the size of a view? Think about its intrinsic content size. Want to think about the position of a view? Think about its offset from other views in the interface. A button doesn’t have a frame of {20, 40, 200, 40}, no, it is 10 points below a label, centered on the Y axis of its superview and wants to fit its title comfortably.

4. Change constants, not constraints

One of the more useful (and difficult) features of autolayout is the ability to make dynamic user interfaces. If your model changes and a new button needs to move into place, don’t delete the current constraint and create a new one. Finding constraints at runtime is not straightforward, but modifying the constant of a constraint is very simple. If a button needs to slide in from the right side of the screen, create a constraint where initially button.left = superview.left + 400. When it comes time to slide it in, change the constant so that the equation is button.left = superview.left + 200. Bonus: animation comes for free:

[[self buttonEdgeConstraint] setConstant:200];
[UIView animateWithDuration:0.5 animations:^{
[[self button] layoutIfNeeded];
}];

5. Understand the limitations and bugs

Right now, setting up constraints in a XIB file for a UITableViewCell doesn’t do what you expect it to do: each constraint thinks that the superview is the instance of UITableViewCell, not the cell’s contentView. This means that you will never get what you expect. Instead, turn off autolayout for a UITableViewCell XIB and either set up constraints programmatically or use autoresizing masks.

When modifying a XIB, Xcode won’t let you set up constraints that are invalid (for the most part). That means if you have a constraint you don’t want, you may have to add another constraint before you can delete it.

The thickness of the constraint line in the XIB is your key: a thin blue line is a required constraint, whereas the thicker blue line is a user constraint. Required constraints can’t be deleted, otherwise, the layout would become invalid. When a set of constraints over-qualifies a view’s frame, the constraints that aren’t necessary automatically become user constraints that can be deleted. For example, if you plop a text field onto the screen, it may set up a left and right edge constraint. If you don’t want the right edge constraint, pin the width of the text field – this makes the right edge and width constraints redundant. Then you can delete the right edge constraint and the width constraint will become required.

View Controller Lifecycle in iOS 6

Some of you may have noticed that your view controllers no longer get sent viewWillUnload or viewDidUnload in iOS 6. That’s because your view controllers don’t automatically unload their views anymore.

Your first thought may be, “Ok, well how do I manually unload my views on a low memory warning? This seems like a step backwards.”

Then you go searching for an answer, and you come up with this:

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    if([self isViewLoaded] && ![[self view] window]) {
        [self setView:nil];
    }
}

However, this is both unnecessary and potentially harmful because of some changes to the underlying support for UIViews. Therefore, in practice, you rarely need to unload a view controller’s view during a low memory warning. (And in theory, you will never have to.)

But why? If you’ve read our entire iOS programming book, you’ve gained the knowledge that a UIView is a subclass of UIResponder (so that it can receive events) and has a pointer to its own CALayer instance (so that it can be drawn on the screen).

A CALayer is a container for a bitmap image. When a UIView runs its drawRect: method, it is creating the bitmap image for its layer. The rest of a layer’s instance variables (many of which it borrows from its UIView, like its frame and backgroundColor) indicate how and where that bitmap image is composited onto the screen.

But the biggest part of the layer (in terms of memory usage) is that bitmap. A layer itself is only 48 bytes and a standard UIView is only 96 bytes, regardless of their size on the screen. The memory consumption for a layer’s bitmap, however, grows very large depending on the bounds of the layer. For example, a full screen retina-display iPad view can be up to a whopping 12 megabytes.

The approach taken by iOS 6 is that a low memory warning should only destroy the layer’s bitmap, but keep the CALayer and UIView objects intact. This makes sense given the memory consumption of the view and layer are relatively small compared to the bitmap. Additionally, a bitmap can be redrawn by having the view run drawRect: again, so it is not like we’ve lost anything.

In fact, something is gained by this approach: your controller no longer needs to re-populate view content after a low memory warning. For example, consider a view controller that maintained a couple of text fields. If that view controller’s view were to go off screen and a low memory warning were to occur, the view controller must save the text currently in those text fields and repopulate them in viewDidLoad or viewWillAppear:. This is no longer an issue because the text fields are never destroyed, thus they retain their text for when the text field’s bitmap is drawn again. This simplifies a very error-prone section of UIViewController code.

There are some additional smarts built into this process of dumping the layer’s bitmap image that are really cool. First, let’s make sure we understand allocation and deallocation. When a memory is allocated (an object, a bitmap, whatever), an appropriately sized chunk of memory from the heap is marked as “in use” and a pointer to the beginning of that chunk of memory is returned. In the case of an object allocation, we think of that pointer as “the object” but really, it’s just the address of a chunk of “in use” memory.

While a chunk of memory is allocated (“in use”), there are guards that prevent code from using that memory unless it is accessed by going through the pointer that was returned during allocation. In a sense, that memory is safe from being screwed with unless you intend to screw with it.

Deallocation simply removes those guards and marks that chunk of memory as “not in use”. This means that the next time you allocate an object, you can use some or all of that “not in use” memory to form a new allocation. Upon deallocation, the values stored in that chunk of memory do not change. While it is possible to access that deallocated memory again and it may be the same, chances are that the memory has changed in some way. Therefore, it’s never safe to access deallocated memory through the pointer you were given upon allocation.

Now, on to why this matters for views and their layers. Each layer has a contents property that points to an object that represents the layer’s bitmap. The type of this object is a private, opaque class named CABackingStore, which contains the actual bitmap as well as some metadata (like whether or not the image has an alpha channel and how many bytes per pixel are used). Thus, it is the CABackingStore that needs to be destroyed when memory is running low.

However, the neat trick here is that a low memory warning does not destroy a CABackingStore. Instead, if a view is offscreen during a low memory warning, its layer’s CABackingStore is set to “volatile”. The volatile flag (which is not the same as the volatile keyword in C), in this context, is like deallocation in the sense that it allows the memory of the CABackingStore to be allocated for a different purpose. The difference between marking this memory as volatile and deallocating it is that the volatile memory can actually be reclaimed; it is not lost forever.

Consider why this is such an interesting optimization. If a view (more accurately, its layer) were to destroy its backing store, the next time the view went on screen it would have to recreate that backing store by running drawRect:. drawRect: is an expensive call, so avoiding it is very important. By allowing the backing store to be reclaimed, the layer can avoid having its UIView execute drawRect: again.

Of course, it is possible that some time between when the backing store was marked as volatile and the view that owned it goes back on the screen, the memory for that backing store was reallocated for a different purpose. In that case, the view would have to run its drawRect: method again to produce its bitmap.

My iPhone 5 experience

I’d like to talk to you today about all of the cool new features of the iPhone 5 that shipped to me last week. I’d like tell you how the Maps app needs some work, but it is a good first step. I’d also like to tell you how interesting it is to use Siri after being on an iPhone 4 for the last two years.

But I won’t be telling you any of that, because my iPhone 5 won’t activate. Why won’t it activate? Let me take you through that lovely process.

My iPhone 5 arrives sometime last week – I don’t know when exactly, as I was teaching a class, you know, spreading the iOS gospel. When I got home, I turned it on and started going through the activation process. Having to type my Wifi password on the iOS keyboard is never fun, but eventually, I came up with the right combination of characters, numbers and shift-key presses.

Now, the Apple server tries to activate my phone and replies with something interesting: apparently, my phone number is from the 916 area code. Now, you might look up that area code and say, “That makes sense, NorCal area code, Joe’s a programmer… totes makes sense.” Not “totes”. I live in Atlanta. My area code is 404.

This is not my phone.

But whatever, iTunes says just continue the activation process anyway and call AT&T afterwards. iTunes asks for my billing zip code and last four digits of my SSN. Type those in… no good, Apple doesn’t recognize that as the correct information. I try again with my home zip code, no good. Maybe it’s my SSN? I know the US government is going to try and forget my SSN when I retire, but no, I remembered mine correctly.

iTunes says to call Apple after it locks me out of my own phone. I call Apple. They say I have to go to the Apple store and I reluctantly agree. You see, I despise the Apple store. Perhaps you don’t know me enough to know that my patience level for anything that involves laziness is absolutely zero. Taking up a spot in the Apple Genius line to figure out how to open iPhoto gets on my least forgiving nerve. Even the TSA has a special lane for people who know what they are doing.

Anyhow, Apple genius insists that this is an AT&T problem. He calls AT&T and has them point my phone’s unique identifier (IMEI) and SIM card (ICCID) at my account (which, as I found out later, already was pointing at my account). However, this doesn’t fix it. I trust the Apple guy when he says it may take awhile for the changes to propagate from AT&T’s server to Apple’s server and head home. After all, I have a working iPhone 4, and it’s not like I do anything that interesting on my iPhone except play Risk while sitting on the can.

I go home to get some rest, since I took the red-eye home from Seattle the night before – and I’m an exceptionally unpleasant person to be around when I’m either tired or jet-lagged – so I could imagine the toll I was taking on my girlfriend was hovering somewhere around the “Facebook official break-up” level. I wake up in the morning and try to activate my phone: no dice, still the wrong number. I go to call AT&T.

My iPhone 4 doesn’t work.

Ok, so I don’t have a phone at all. I hop online and get an AT&T service rep via chat, who tells me to go to the AT&T store. AT&T store guy is super nice, insists they’ve made a mistake and says we are going to figure it out. He checks my account and everything should be working. He calls corporate AT&T. They think everything should be working. So myself, the AT&T store rep and the AT&T corporate rep all get on a conference call with an Apple rep.

Now, we don’t have all day, so let me fast-forward 90 minutes: Apple escalates the call to a senior supervisor who now knows (supposedly) what the problem is. You see, Apple’s activation server doesn’t really care about the carrier or the IMEI or the Sim card or anything interesting. Apple cares about the serial number. Apple’s server maps the device’s serial number to a particular account. So, while my iPhone 5 is talking nicely with AT&T’s server (I have cell coverage), I can’t get past the activation screen because Apple sent me the wrong phone. Apparently, this is somewhat common and involves a data entry person committing a typo.

Changing this mapping – also known as undoing a typo – takes 4 hours. So here I am sitting without a phone, although, Microsoft was kind enough to send me a nice Windows phone. For free. I hear .NET is nice this time of year.

Changing the color of the Xcode Insertion Cursor

I have three monitors in my office, all three of which typically have Xcode open. My Xcode editor background color is also a really dark gray.

Needless to say, figuring out what I’m about to click feels like navigating a “Where’s Waldo?” book by moonlight.

I finally decided to fix it, and if you suffer from the same problem, I have a solution for you. (Also, I’ve started work on updating the iOS class materials, so I’m shamelessly re-sharpening my writing skills and passing this off as an amazing revolution in software development.)

Inside the Xcode application bundle (right-click, Show Package Contents on the Xcode app icon), look for Contents/Shared/Frameworks/DVTKit.framework/A/Resources directory. In this directory, there is a file named DVTIbeamCursor.png (or .tiff, depending on the version of Xcode you are running).

Make a copy of this file on your desktop, and open the copy in preview. Then, select Adjust Color… from the Tools menu. Drag the Contrast slider all the way to the left and then move the Exposure slider a bit to the right. The insertion cursor is now a lovely shade of gray. (Alternatively, you can open up this image in any image editor and do whatever you want to it, but I don’t have that kind of fancy software, nor would I know how to use it.)

Finally, save the image and drag it back into the directory it came from – you’ll have to authenticate with the Finder to pull this off, because messing with application bundles is apparently bad form.

If you are running a newer version of Xcode, make sure you also modify the DVTIbeamCursor@2x.png file, too.

Follow

Get every new post delivered to your Inbox.

Join 33 other followers