UITableViewCells

One of the biggest mistakes Apple made in the design of the iOS API was to expose the component views within a UITableViewCell.

Okay, so it really wasn’t Apple’s fault; they wanted to solve the problem of providing access to the components of a table view cell so we could use the off-the-shelf parts easily in our application. By exposing the textLabel, detailTextLabel and imageView UIView components, it makes it easy for us to modify the off-the-shelf parts to our own needs, providing a look which is consistent with the rest of the iOS universe.

But it was a mistake because it taught an entire generation of iOS developers some really bad habits.


One of the things that I greatly appreciate about object oriented programming is that it allows us to easily design applications as a collection distinct separate objects with well-defined purposes or tasks. This separation of concerns permits us to create modular classes, which have the following advantages:

  • Maintainable code. By isolating components into well-defined objects, a modification that needs to be made to one section of the code will, in a worse case scenario, require minor modifications in some other isolated areas of the code. (This, opposed to “spaghetti code” where one change ripples throughout the entire application.)
  • Faster development. Modules which are required by other areas of the application but which haven’t been developed yet can be “mocked up” in the short term to permit testing of other elements of the code.
  • Simplified testing. Individual modules can be easily tested and verified as correct within their limited area of concern. Changes that need to be made to fix a bug in an individual module or object can be made without major changes in the rest of the application.

There are others, but these are the ones I rely upon on a near daily basis as I write code.

Now why do I believe Apple screwed up?

Because it discourages the creation of complex table views (and, by extension, complex view components in other areas of the application) as isolated and well-defined objects which are responsible for their own presentation, and instead encourages “spaghetti code” in the view controller module.

Here’s a simple example. Suppose we want to present a table view full of stock quotes, consisting of the company name, company ticker symbol, current quote and sparkline–a small graph which shows the stock’s activity for the past 24 hours.

Suppose we code our custom table cell in the way that Apple did: by creating our custom view, custom table layout–and then exposing the individual elements to the table view controller.

Our stock data object looks like:

@interface GSStockData : NSObject

@property (readonly) NSString *ticker;
@property (readonly) NSString *company;
@property (readonly) double price;
@property (readonly) NSArray *history;
...
@end

This would give us a stock table view cell that looks like this:

#import 
#import "GSSparkView.h"

@interface GSStockTableViewCell : UITableViewCell

@property (strong) IBOutlet UILabel *tickerLabel;
@property (strong) IBOutlet UILabel *companyLabel;
@property (strong) IBOutlet UILabel *curQuoteLabel;
@property (strong) IBOutlet GSSparkView *sparkView;

@end

And our table view controller would look like this:

#import "GSStockTableViewController.h"
#import "GSStockData.h"
#import "GSStocks.h"
#import "GSStockTableViewCell.h"

@interface GSStockTableViewController ()

@end

@implementation GSStockTableViewController

#pragma mark - Table view data source

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [[GSStocks shared] numberStocks];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
	GSStockTableViewCell *cell = (GSStockTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"StockCell" forIndexPath:indexPath];

	GSStockData *data = [[GSStocks shared] dataAtIndex:(int)indexPath.row];

	cell.tickerLabel.text = data.ticker;
	cell.companyLabel.text = data.company;
	cell.curQuoteLabel.text = [NSString stringWithFormat:@"%.2f",data.price];
	[cell.sparkView setValueList:data.history];

    return cell;
}

@end

Seems quite reasonable, and very similar to what Apple does. No problems.

Until we learn that the API has changed, and now in order to get the stock price history for our stock, we must call an asynchronous method which queries a remote server for that history. That is, instead of having a handy history of stocks in ‘history’, instead we have something like this:

#import 
#import "GSStockData.h"

@interface GSStocks : NSObject

+ (GSStocks *)shared;

- (int)numberStocks;
- (GSStockData *)dataAtIndex:(int)index;

- (void)stockHistory:(int)index withCallback:(void (^)(NSArray *history))callback;
@end

That is, in order to get the history we must obtain it asynchronously from our stock API.

What do we do?

Well, since the responsibility for populating the table data lies with our view controller, we must, on each table cell, figure out if we have history, pull the history if we don’t have it, then refresh the table cell once the data arrives.

So here’s one approach.

(1) Add an NSCache object to the table view controller, and initialize in viewDidLoad:

@interface GSStockTableViewController ()
@property (strong) NSCache *cache;
@end

@implementation GSStockTableViewController

- (void)viewDidLoad
{
	self.cache = [[NSCache alloc] init];
}

(2) Pull the history from the cache as we populate the table contents. If the data is not available, set up an asynchronous call to get that data.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
	GSStockTableViewCell *cell = (GSStockTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"StockCell" forIndexPath:indexPath];

	GSStockData *data = [[GSStocks shared] dataAtIndex:(int)indexPath.row];

	cell.tickerLabel.text = data.ticker;
	cell.companyLabel.text = data.company;
	cell.curQuoteLabel.text = [NSString stringWithFormat:@"%.2f",data.price];

	/*
	 *	Determine if we have the contents and if not, pull asynchronously
	 */

	NSArray *history = [self.cache objectForKey:@( indexPath.row )];
	[cell.sparkView setValueList:history];		// set history
	if (history == nil) {
		/* Get data for cache */
		[[GSStocks shared] stockHistory:data withCallback:^(NSArray *fetchedHistory) {
			/*
			 *	Now pull the cell; we cannot just grab the cell from above, since
			 *	it may have changed in the time we were loading
			 */

			GSStockTableViewCell *stc = (GSStockTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
			if (stc) {
				[stc.sparkView setValueList:fetchedHistory];
			}
			[self.cache setObject:fetchedHistory forKey:@( indexPath.row )];
		}];
	}

    return cell;
}

Notice the potential problems that can happen here. For example, if a user didn’t understand that a cell may be reused by the tableview, the wrong sparkline could be placed in the tableview if the user scrolls rapidly:

	NSArray *history = [self.cache objectForKey:@( indexPath.row )];
	[cell.sparkView setValueList:history];		// set history
	if (history == nil) {
		/* Get data for cache */
		[[GSStocks shared] stockHistory:data withCallback:^(NSArray *fetchedHistory) {
			/*
			 *	Now pull the cell; we cannot just grab the cell from above, since
			 *	it may have changed in the time we were loading
			 */

			// The following is wrong: the cell may have been reused, and this
			// will cause us to populate the wrong cell...
			[cell.sparkView setValueList:fetchedHistory];
			[self.cache setObject:fetchedHistory forKey:@( indexPath.row )];
		}];
	}

And that’s just one asynchronous API with a simple interface. How do we handle errors? What if there are multiple entry points? What if other bits of the code is using the table view?

Now if we had put all the responsibility for displaying the stock quote into the table view cell itself:

#import 
#import "GSStockData.h"

@interface GSStockTableViewCell : UITableViewCell

- (void)setStockData:(GSStockData *)data;

@end

Then none of the asynchronous calling to get values and properly refreshing the cells is the responsibility of the table view cell. All it has to do is:

#pragma mark - Table view data source

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [[GSStocks shared] numberStocks];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
	GSStockTableViewCell *cell = (GSStockTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"StockCell" forIndexPath:indexPath];

	GSStockData *data = [[GSStocks shared] dataAtIndex:(int)indexPath.row];
	[cell setStockData:data];

    return cell;
}

@end

This is much cleaner. And for our table cell, because it has all the responsibility of figuring out how to populate the contents, if we have to rearrange the cell, it has zero impact on our table view controller.

Our table view cell becomes relatively straight forward as well:

#import "GSStockTableViewCell.h"
#import "GSSparkView.h"
#import "GSStocks.h"

@interface GSStockTableViewCell ()
@property (strong) GSStockData *currentData;

@property (strong) IBOutlet UILabel *tickerLabel;
@property (strong) IBOutlet UILabel *companyLabel;
@property (strong) IBOutlet UILabel *curQuoteLabel;
@property (strong) IBOutlet GSSparkView *sparkView;
@end

@implementation GSStockTableViewCell

- (void)setStockData:(GSStockData *)data
{
	self.tickerLabel.text = data.ticker;
	self.companyLabel.text = data.company;
	self.curQuoteLabel.text = [NSString stringWithFormat:@"%.2f",data.price];

	/*
	 *	If the history was in our object then we'd write the following:
	 */

	// [self.sparkView setValueList:data.history];

	/*
	 *	Instead we get it through a call to our data source
	 */

	self.currentData = data;	/* Trick to make sure we still want this data */
	[[GSStocks shared] stockHistory:data withCallback:^(NSArray *fetchedHistory) {
		/*
		 *	Verify that the history that was returned is the same as the
		 *	history we're waiting for. (If another call to this is made with
		 *	different data, self.currentData != data, as data was locally
		 *	cached in our block.
		 */

		if (self.currentData == data) {
			[self.sparkView setValueList:fetchedHistory];
		}
	}];
}

@end

And what about our caching?

Well, if we’re using proper separation of concerns, we’d create a new object which was responsible for caching the data from our API. And that has the side effect of being usable everywhere throughout the code.


My point is simple: unless you are using the canned UITableViewCell, make your table view cell responsible for displaying the contents of the record passed to it. Don’t just expose all of the internal structure of that table cell to your view controller; this also pushes responsibility for formatting to the view controller, and that can make the view controller a tangled mess.

Make each object responsible for one “thing”: the table view cell is responsible for displaying the data in the stock record, including fetching it from the back end. The view controller simply hands off the stock record to the table view cell. A separate class can be responsible for data caching. And so forth.

By making each object responsible for it’s “one thing”, it makes dealing with changes (such as an asynchronous fetch of history) extremely easy: instead of having to modify a view controller which slowly becomes extremely overloaded, we simply add a few lines of code to our table view cell–without actually expanding our class’s “responsibility” for displaying a single stock quote.


And in the end you’ll reduce spaghetti code.

Security

Just read the following article: Security Trade-Offs, which refers to an original article claiming that people need to stop trusting Apple with their data because Apple, as a purveyor of “Shiny Objects”, doesn’t understand security.

Which is funny because the original article shows a lack of knowledge of computer security.

I’ve encountered this lack of understanding of security when talking to friends and co-workers as well, and it irritates me. Worse, they “know” they’re right, because of course it’s incredibly obvious, and they’ve read all sorts of stuff which reaffirm their ignorance thinking they were learning something new.

(Sigh.)


Security involves three aspects, not just one–and to better understand each of these issues we can think of a house rather than a computer. After all, for your house to be a home, it’d be nice to know it was physically secure, right?

The three fundamental aspects of security are Confidentiality, Integrity and Availability.

For your house to be secure, it needs to be “confidential”: meaning access controls need to be implemented to prevent people who do not have access to get in. That’s the lock on your front door: the house needs to be locked, your house (just one of a bunch in a neighborhood) is somewhat anonymous, perhaps drapes on the front windows will help people see you don’t have an expensive stereo system and big screen TV inside.

Now the mistake most people make is that they stop here: as long as people can’t break into my house, all is well. But keeping people out of your house is dirt simple: just cover the front door with cement. Bury your house under a mound of dirt. No-one can enter your house if it is encased in a sealed metal box–not even you.

Sure, we can talk about two factor authentication and if our default of putting patio furniture outside makes sense or we should chain your patio furniture down with bolts in your back yard or keep your patio furniture inside your house so someone can’t jump the fence and steal it.

But all this ignores the two other dimensions of security: availability and integrity.

Availability means can you get into your house easily, or are you going to be outside fumbling with your multiple keys and trying to remember button combinations while standing in the rain? Does your house do what you want–can you move from room to room easily and look at the view from the bedroom window–or are the windows encased in bars and are you constantly having to unlock the door to your bathroom? (After all, your house would be more secure if every door was equipped with a combination lock which automatically locked when the door automatically closed.)

And integrity: does all the weight of those metal plates and the bars on the window corrupt the appearance of your house or make part of it structurally weak and cause the back bedroom to collapse? Sure, you can reduce the attack profile of your house by barring up all the windows–preventing crooks from breaking in by breaking through the window. But you’ve corrupted the functionality of your house: you’ve made it difficult to evacuate your house in the event of a fire. (People have died because of this.)

And sure, the default of putting your patio furniture unlocked in the back yard where it can be stolen by any miscreant capable of climbing a fence makes no sense if you only look at access controls–but if your guests cannot move the patio furniture around freely or you’re constantly dragging the furniture out from a locked garage (locked with a combination lock and separate deadbolt lock), you’re not going to use your patio.

The lack of easy availability of your patio furniture, in other words, means you may as well not have any furniture outside.


Think of Apple as the developer of a subdivision of homes. They all have similar front door locks, similar patios, similar layouts. Apple made those houses convenient and pretty and nice for people to use.

And now a bunch of homes got broken into, and people are (rightfully) asking Apple if somehow the design of the house make it easy for the burglars to break in. And after looking at the corner security cameras, Apple concluded that only specific homes were targeted by burglars who somehow copied the keys to the front door using ‘social engineering’ means: people followed the owners of those homes around with silly putty, and managed to get an imprint of the front door key.

The fact that Apple made it easy to open the front door with just a key is not a stupid vulnerability, as the original Slate article implies.

And in fact, the Slate article ignores the single most common security attack used against computer systems and homes alike: social engineering. Which is just a fancy way of saying that if someone spends the time befriending you at the local bar, and then asks you to show him what’s on your computer system or inside your house–you’ll happily bypass security for them by holding the front door open, or handing him your unlocked phone.

Social engineering was apparently used for most of the break-ins to get into Apple iCloud accounts–by determining the e-mail address of various celebrity accounts (stalking the neighborhood to see who lives where), and then following those celebrities around trying to guess their password (taking pictures of the people who live in the neighborhood hoping to get a glance of the key so one can be made from the photo).

This sort of thing happened over the course of years and wasn’t limited to just Apple’s neighborhood; Android and Windows Mobile devices were also hacked. And this was a sophisticated ring who had gathered stolen images over years.

In fact, the only place where the analogy breaks down is that until the leak this past weekend, we had no idea stuff had been stolen.


Does this mean we should start blaming Apple for building houses with front door windows whose drapes are sometimes left open, which can be opened with a single front door key? Should we demand Apple go back and board up the windows and put multiple locks on everyone’s door? Should Apple patrol the neighborhood and force people who leave patio furniture out in the back yard to bolt it down with bolts sunk in cement, or at least move them into the garage when not in use?

Should Apple go back and retrofit interior doors with automatically locking locks and automatically closing doors?

Or does this mean those who have more to protect should be more thoughtful about protecting their stuff?

Bringing it back to the computer model, should we all be forced to use two factor authentication to access our photos on the Cloud, using a password that may be forgotten and cannot be reset, and a thumb print reader that flakes out when the sensor gets dirty–just to protect the occasional picture I may snap while hiking or the occasional selfie someone may take in front of a museum exhibit–simply because a few starlets took naked pictures of themselves they intended only for their boyfriends, pictures that were then stuck on a server using an inadequate password managed by a handler who then scraped the naked photos off the phone without the starlet knowing?

After all, it was not my iCloud account that was targeted. And even if my photos happened to be scraped from iCloud–all you would see are bird photos and hiking photos and the occasional photo shot from an airplane: worthless crap to anyone who is not me or in my immediate circle of friends.


And while we’re on the topic, let’s talk “factors.”

All access control boils down to three factors: who you are, what you know and what you have.

An ATM is “two factor authentication”: it relies on you having an ATM card, and knowing your PIN. Scanners which know “who you are” rely on some physical attribute: think finger print scanners or retina scanners or devices that measure relative finger lengths.

The problem with always going back to using multiple “factors” ignores the fact that some factors are strong, and some are weak. A 4 digit PIN is a weak password. As Mythbusters showed, fingerprint scanners are moderately weak. And the ready availability of card readers have made ATM cards weak: given that most ATM cards now double as debit cards, it would be easy for a waitress to scan your card at a restaurant, duplicating your ATM/debit card with just a swipe.

Combining factors make things stronger: combining a 4 digit PIN with your ATM card makes it safe to hand just your card to your waitress. Using a key fob which generates a cryptographically pseudo-random number combined with a relatively strong password makes an even stronger security gateway. One place I knew which hosted servers required you to present an identity card, get through a palm scanner, and know an 8 digit PIN to enter the cage.

But all of this is worthless if the guard leaves the door open–which they did on occasion.

The point is two factor authentication is not a cure-all. Two factor authentication can make weak security (such as a 4 digit pin) stronger (by requiring a card as well), but it doesn’t save you from social engineering, such as asking a security guard to keep a door open as you bring in a bunch of boxes. Having a combination padlock on your front door along with a key-activated deadbolt doesn’t help if you leave your front door unlocked.

And worse, two factor authentication violates availability. And why availability is important is simple: the harder it is to get into the front door lock of your house, the less likely you are to lock the front door.


Perhaps the real lesson here is twofold. First, a dedicated burglar will break into your house if the incentive is high enough, regardless of the security checks: remember, while everyone is looking at Apple’s iCloud, other services were broken into as well: these photos came from a variety of sources, and iCloud was a common target only because it was the largest neighborhood.

So part of the problem is just a matter of keeping the drapes closed, so the burglars can’t see your expensive stereo and big-screen TV.

Second, it means you need to be a little bit aware of your neighborhood: if you have something important to secure, perhaps a little additional attention is in order. If you’re a young and beautiful starlet taking naked pictures of yourself, you may want to consider not putting those photos up on the Internet.

But then, most starlets who took these photos did not consider security at all–they did not consider these photos as having any value. And so even if Apple made two factor authentication dirt simple, passwords would have been set to “1234” and the option to double-encrypt the individual files would have been set to “no”. After all, it was just a fun nude photo between her and her boyfriend–no biggie. Right?

Because we don’t understand security: we think its okay to leave the front drapes open and the front doors unlocked, until someone breaks in–at which point we demand our houses be encased in cement.

Finding the boundary of a one-bit-per-pixel monochrome blob

Recently I’ve had need to develop an algorithm which can find the boundary of a 1-bit per pixel monochrome blob. (In my case, each pixel had a color quality which could be converted to a single-bit ‘true’/’false’ test, rather than a literal monochrome image, but essentially the problem set is the same.)

In this post I intend to describe the algorithm I used.


Given a 2D monochrome image with pixels aligned in an X/Y grid:

Arbitrary 2D Blob

We’d like to find the “boundary” of this blob. For now I’ll ignore the problem of what the “boundary” is, but suffice to say that with the boundary we can discover which pixels are inside the blob which border the exterior of the blob, which pixels on the outside border the pixels inside the blob, or to find other attributes of the blob such as a rectangle which bounds the blob.

If we treat each pixel as a discrete 1×1 square rather than a dimensionless point, then I intend to define the boundary as the set of (x,y) coordinates which define the borders around each of those squares, with the upper-left corner of the square representing the coordinate of the point:

Pixel Definition

So, in this case, I intend to define the boundary as the set of (x,y) coordinates which define the border between the black and the white pixels:

outlined blob

We do this by walking the edge of the blob through a set of very simple rules which effectively walk the boundary of the blob in a clock-wise fashion. This ‘blob walking’ only requires local knowledge at the point we are currently examining.

Because we are walking the blob in a clock-wise fashion, it is easy to find the first point in a blob we are interested in walking: through iteratively searching all of the pixels from upper left to lower right:

(Algorithm 1: Find first point)

-- Given: maxx the maximum width of the pixel image
          maxy the maximum height of the pixel image

   Returns the found pixel for an eligable blob or 'PixelNotFound'.

for (int x = 0; x < maxx; ++x) {
    for (int y = 0; y < maxy; ++y) {
        if (IsPixelSet(x,y)) {
            return Pixel(x,y);
        }
    }
}
return PixelNotFound;

Once we have found our elegable pixel, we can start walking counter clockwise, tracking each of the coordinates we have found as we walk around the perimeter of the blob, traversing either horizontally or vertically.


Given the way we’ve encountered our first pixel in the algorithm above, the pixels around the immediate location at (x,y) looks like the following:

Point In Center

That’s because the way we iterated through, the first pixel we encountered at (x,y) implies that (x-1,y), (x,y-1) and (x-1,y-1) must be clear. Also, if we are to progress in a clock-wise fashion, clearly we should move our current location from (x,y) to (x+1,y):

Blob5


The design of our algorithm proceeds in a similar fashion: by examining each of the 16 possible pixel configurations we can find in the surrounding 4 pixels, and tracking the one of 4 possible incoming paths we take, we can construct a matrix of directions in which we should take to continue progressing in a clockwise fashion around our eligible blob. And in all but two configuration cases, there was only one possible incoming path we could have taken to get to the center point, since as we presume we are following the edge of the blob we could not have entered between two black pixels or between two white pixels. Some combinations are also illegal since we presume we are walking around the blob in a clock-wise fashion rather than in a counter-clockwise fashion. (This means that we should be, when standing at the point location, pixels should be on the right and never on the left. There is a proof for this which I will not sketch here.)

The 16 possible configurations and the outgoing paths we can take are illustrated below:

All directions

Along the top of this table shows the four possible incoming directions: from the left, from the top, from the right and from the bottom. Each of the 16 possible pixel combinations are shown from top to bottom, and blanks indicate where an incoming path was illegal–either because it comes between two blacks or two whites, or because the path would have placed the black pixel on the left of the incoming line rather than on the right.

Note that with only two exceptions each possible combination of pixels produces only one valid outgoing path. Those two exceptions we arbitrarily pick an outgoing of two possible paths which excludes the diagonal pixel; we could have easily gone the other way and included the diagonal, but this may have had the property of including blobs with holes. (If this is acceptable or not depends on how you are using the algorithm.)

This indicates that we could easily construct a switch statement, converting each possible row into an integer from 0 to 15:

Algorithm 2: converting to a pixel value.

-- Given: IsPixel(x,y) returns true if the pixel is set and false 
          if it is not set or if the pixel is out of the range from
          (0,maxx), (0,maxy)
   Return an integer value from 0 to 15 indicating the pixel combination

int GetPixelState(int x,y int y)
{
    int ret = 0;
    if IsPixel(x-1,y-1) ret |= 1;
    if IsPixel(x,y-1) ret |= 2;
    if IsPixel(x-1,y) ret |= 4;
    if IsPixel(x,y) ret |= 8;
    return ret;

}

We now can build our switch statement:

Algorithm 3: Getting the next pixel location

-- Given: the algorithm above to get the current pixel state,
          the current (x,y) location,
          the incoming direction dir, one of LEFT, UP, RIGHT, DOWN

   Returns the outgoing direction LEFT, UP, RIGHT, DOWN or ILLEGAL if the
   state was illegal.

Note: we don't test the incoming path when there was only one choice. We
could, by adding some complexity to this algorithm, for testing purposes.
The values below are obtained from examining the table above.

int state = GetPixelState(x,y);
switch (state) {
    case 0:    return ILLEGAL;
    case 1:    return LEFT;
    case 2:    return UP;
    case 3:    return LEFT;
    case 4:    return DOWN;
    case 5:    return DOWN;
    case 6:    {
                   if (dir == RIGHT) return DOWN;
                   if (dir == LEFT) return UP;
                   return ILLEGAL;
               }
    case 7:    return DOWN;
    case 8:    return RIGHT;
    case 9:    {
                   if (dir == DOWN) return LEFT;
                   if (dir == UP) return RIGHT;
                   return ILLEGAL;
               }
    case 10:   return UP;
    case 11:   return LEFT;
    case 12:   return RIGHT;
    case 13:   return RIGHT;
    case 14:   return UP;
    case 15:   return ILLEGAL;
}

From all of this we can now easily construct an algorithm which traces the outline of a blob. First, we use Algorithm 1 to find an eligible point. We then set ‘dir’ to UP, since the pixel state we discovered was pixel state 8, and the only legal direction had we been tracing around the blob was UP.

We store away the starting position (x,y), and then we iterate through algorithm 3, getting new directions and updating (x’,y’), traversing (x+1,y) for RIGHT, (x,y+1) for UP, (x-1,y) for LEFT and (x,y-1) for DOWN, until we arrive at our starting point.

As we traverse the parameter, we could either build an array of found (x,y) values, or we could do something else–such as maintaining a bounding rectangle, bumping the boundaries as we find (x,y) values that are outside the rectangle’s boundaries.

First pass at a more formal language for JSON.

So the single most common thing I run into, which is a source of all sorts of headaches when writing custom software for clients, is hooking into their back end system.

A very common pattern for me is to create a single interface which can perform a HTTP ‘get’ or ‘post’ call in order to obtain the contents, run everything through a JSON parser, and then handing the resulting NSDictionary or NSArray to an object which converts the results into a set of Objective C classes.

Up until now I’ve been using JSON Accelerator, which is a really nice little tool for converting JSON into a set of classes. But this runs into a couple of problems.

(1) A number of sites I integrate with have multiple JSON endpoints, each which return subtly different JSON results. Using JSON Accelerator and I wind up generating a lot of duplicate classes which represent more or less the same thing.

(2) Often those sites will change; after all, the back end is under development as well as the front end. I often have a hard time seeing the structure from the JSON; sometimes buried in a few hundred lines is a field that contains a null pointer or which was changed from a string to a JSON field–and tracking those bugs down can be a pain in the ass.

It seemed to me the best way to handle this is to have an intermediate representational language which allows me to see what it is that I’m working with, and to allow allow me to ‘tweak’ the results, so I can point out that the ‘Person’ record in call A is the exact same thing as the ‘Person’ record in call B, except for one of the fields being omitted.

So I built a simple analysis app and a simple compiler app to resolve this problem.

You can download the compiled tools and read the documentation (such as it is) from here.

The representational language is fairly simple: a set of objects, which can be compiled into Objective C and (when I have time) into Java. Each field in an object can be a primitive, an object or an array of objects. So, for example:

/*  Feed 
 *
 *      Top level of the feed
 */

Feed {
    id: integer,
    name: string,
    date: string,
    active: boolean,
    addressList: arrayof Address,
    phoneList: arrayof Phone,
}

/*  Address
 *
 *      The user's address
 */

Address {
    id: integer,
    name: string,
    address: string,
    address2: (optional) string, // optional in the data stream
    city: string,
    state: string,
    zip: string
}

/*  Phone
 *
 *      The user's phone
 */

Phone {
    id: integer,
    name: string,
    phone: string
}

Note that fields can also be marked as ‘nullable':

Feed {
    id: integer,
    name: string,
    value: (nullable) real
}

This will translate into an NSNumber * field rather than into a double.

There are also a couple of tools: one that generates the Objective C code, and one which reads in a bunch of JSON (in fact, it will read multiple JSON objects all in a row), and makes a best guess at the underlying structure, collapsing common objects as needed, and even noting when the same field appears to contain ambiguous content.


At some point I will need to clean this up, add Java support, and push this out to GIT. But for now, there you go.

Let me know if this seems useful.

Handy trick: trap back button in a UINavigationController stack

- (void)didMoveToParentViewController:(UIViewController *)parent
{
	[super didMoveToParentViewController:parent];

	if (![parent isEqual:self.parentViewController]) {
		NSLog(@"Back");
	}
}

Inserted into a view controller pushed into a UINavigationController stack, this will fire the ‘back’ message when the user presses ‘Back’ to back up the view controller stack.

As seen on Stack Overflow

Moving views around when the keyboard shows in iOS

When the keyboard shows or hides in iOS, we receive an event to notify us that the keyboard is being shown and being hidden.

Ideally we want to get the animation parameters and the size of that keyboard so we can rearrange the views inside of our application to fit the keyboard. I’m only covering the case of the keyboard on the iPhone; on the iPad you also have the problem of the split keyboard, but the same ideas should hold there as well.

Step 1:

When the view controller that may show a keyboard appears, register for notifications for the keyboard being shown and hidden:

- (void)viewDidLoad
{
    [super viewDidLoad];

	// Do any additional setup after loading the view.
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardShowHide:) name:UIKeyboardWillShowNotification object:nil];
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardShowHide:) name:UIKeyboardWillHideNotification object:nil];

	// other stuff here
}

Step 2:

Remember to unregister notifications when this goes away, to prevent problems.

- (void)dealloc
{
	[[NSNotificationCenter defaultCenter] removeObserver:self];
}

Step 3:

Receive the event in our new method, and extract the keyboard parameters and animation parameters.

- (void)keyboardShowHide:(NSNotification *)n
{
	CGRect krect;

	/* Extract the size of the keyboard when the animation stops */
	krect = [n.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];

	/* Convert that to the rectangle in our primary view. Note the raw
	 * keyboard size from above is in the window's frame, which could be
	 * turned on its side.
	 */
	krect = [self.view convertRect:krect fromView:nil];

	/* Get the animation duration, and animation curve */
	NSTimeInterval duration = [[n.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
	UIViewAnimationCurve curve = [[n.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];

	/* Kick off the animation. What you do with the keyboard size is up to you */
	[UIView animateWithDuration:0 delay:duration options:UIViewAnimationOptionBeginFromCurrentState | curve animations:^{
			/* Set up the destination rectangle sizes given the keyboard size */
			Do something interesting here
		} completion:^(BOOL finished) {
			/* Finish up here */
			Do something interesting here
		}];
}

Snippet: code to convert RGB to HSV and back again

I sketched this code together needing a quick way to convert from RGB to HSV and back again, then realized I didn’t need it. So I’m putting it here in the theory that this may be useful someday…

/*	RGBToHSV
 *
 *		Conver to HSV
 */

static void RGBToHSV(float r, float g, float b, float *h, float *s, float *v)
{
	float max = r;
	if (max < g) max = g; 	if (max < b) max = b; 	float min = r; 	if (min > g) min = g;
	if (min > b) min = b;
	
	/*
	 *	Calculate h
	 */
	
	*h = 0;
	if (max == min) h = 0;
	else if (max == r) {
		*h = 60 * (g - b)/(max - min);
		if (*h < 0) *h += 360; 		if (*h >= 360) *h -= 360;
	} else if (max == g) {
		*h = 60 * (b - r) / (max - min) + 120;
	} else if (max == b) {
		*h = 60 * (r - g) / (max - min) + 240;
	}

	if (max == 0) *s = 0;
	else *s = 1 - (min / max);

	*v = max;
}

/*	HSVToRGB
 *
 *		Convert to RGB
 */

static void HSVToRGB(float h, float s, float v, float *r, float *g, float *b)
{
	if (h < 0) h = 0; 	if (h > 359) h = 359;
	if (s < 0) s = 0; 	if (s > 1) s = 100;
	if (v < 0) v = 0; 	if (v > 1) v = 100;

	float tmp = h/60.0;
	int hi = floor(tmp);
	float f = tmp - hi;
	float p = v * (1 - s);
	float q = v * (1 - f * s);
	float t = v * (1 - (1 - f) * s);
	
	switch (hi) {
		case 0:
			*r = v;
			*g = t;
			*b = p;
			break;
		case 1:
			*r = q;
			*g = v;
			*b = p;
			break;
		case 2:
			*r = p;
			*g = v;
			*b = t;
			break;
		case 3:
			*r = p;
			*g = q;
			*b = v;
			break;
		case 4:
			*r = t;
			*g = p;
			*b = v;
			break;
		case 5:
			*r = v;
			*g = p;
			*b = q;
			break;
	}
}

Basic Lessons: Object Oriented Programming with Objects

The really stupid thing, by the way, about most code that I review is how few people know about object oriented development. Yes, yes, yes; they say they know all about object oriented development–but when you then review their code (say, in an iOS application with a table) do they practice proper encapsulation? Nooooooooooo…

All too often I see something like this:

MyTableViewCell.h

@interface MyTableViewCell: UITableViewCell
@property (strong) IBOutlet UILabel *leftLabel;
@property (strong) IBOutlet UILabel *rightLabel;
@end

MyTableViewController.m

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    MyTableViewCell *c = (MyTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"MyTableViewCell" forIndexPath:indexPath];

    c.leftLabel.text = [NSString stringWithFormat:@"Left %d",indexPath.row];
    c.rightLabel.text = @"Right Label";

    return c;
}

The text in red above: no, no, no, no, no.

Haven’t you even heard of encapsulation? No? Well, that’s probably because (a) most developers have no idea what they’re doing beyond copying someone else’s models, and (b) they’ve been taught some bad habits by other developers who also have no idea what they’re doing.

Of course this isn’t helped by Apple, whose own UITableViewCell by default exposes the fields contained within.


What is object encapsulation?

The idea of object encapsulation is central to the idea of object oriented programming. Essentially it refers to the idea of creating “objects”–chunks of data associated with functions designed to work on that data.

To understand how useful this is we need to dive into a pre-OOP language, such as C.

Back in the “bad old days” of C, you had functions, and you had structures. And that was it:

struct MyRecord
{
    int a;
    int b;
};

int AddFields(struct MyRecord x)
{
    return x.a + x.b;
}

While this sort of procedural programming has it’s place–and languages such as C are extremely good at embedded development or in Kernel programming (where execution efficiency is important), it falls short with developing user interfaces, simply because with user interfaces we manipulate things like buttons and text fields and table view cells.

In fact, it turns out that object-oriented programming is tied to user interface development, by abstracting the idea of user interface elements into a new concept of an “object” as a self-contained unit that combines the idea of a structure or record with the idea of functions or procedures that operate on that record.

In C++, we can express this idea as a class:

class MyRecord
{
	int a;
	int b;

	int AddFields();
};


int MyRecord::AddFields()
{
	return a + b;
}

Notice that this expresses the same idea as our C snippet above, which adds the contents of the two fields in MyRecord. Except now, AddFields is associated with a record. This means if we have a record and we want the sum of the fields, instead of writing

MyRecord a;
int sum = AddFields(a);

we write

MyRecord a;
int sum = a.AddFields();

That is, we apply the message against the object.

Now we haven’t really done anything new yet. In fact, if you were to write in C++ the method ‘AddFields()’ from our C example, it would still work with our C++ declaration of MyRecord.

But C++ gives us a new tool: a way of marking fields “private”–that is, only accessible from the methods that are associated with the class.

Thus:

class MyRecord
{
	private:
		int a;
		int b;

	public:
		int AddFields();
};

We’ve hidden a and b from view. Now the only way you can change a and b or get their values is through methods which are then made public with MyRecord.

Encapsulation is the process of creating self-contained objects: objects which provide a clear interface for manipulating the object, but which hide the details as to how the object does it’s work.

Now there was no need to actually use the new features of C++ to provide this sort of data hiding. In C, we can take advantage of the fact that things declared within a single C file stay within that file: we could declare a pointer to a structure in our header file, but hide the details by declaring them in the C file that contains the implementation. C++ makes this easier for us by giving us better tools to manipulate access to the contents of the object.


Why is encapsulation important?

Simply put, encapsulation allows us to separate the “what” from the “how”; separate what we want an object to do from how the object actually does the work.

This becomes important for two reasons.

First, it means that we have an object which has a clearly defined “purpose.” For example we can define an object which represents a button on the screen: a rectangular region the user can tap on or click with their mouse, which then responds to that tap by visually changing appearance and by firing an event which represents the response to that tap or button press.

And second, tied to the first, we can isolate all of the code which handles the button’s behavior within the button itself. A user of the button doesn’t need to know the details of how a button works to put one on the screen, nor does the user need to know how a button receives click or tap events, or how it processes those events. A user doesn’t even need to know the details of how a button draws itself: they don’t need to know how the button handles details such as switching text alignment for languages which read right to left instead of left to right.

And because the details are isolated away, it means those details can change: instead of firing an event on the down click of the mouse the event can be fired when the mouse click is released. The button’s appearance can change–or even be changeable depending on the skin the user selects. The button can even be handled as a spectrum of button-like objects. None of this matter to the user of that button: drop one on the screen, set the text, and wire up the event for the response, and you’re done.


How we can change our object above to respect proper encapsulation

This idea of encapsulation is one that we can–and should follow in our own code. That way if we later have to change the details of how we implement a thing, it doesn’t require us to hunt through all of our code and change the details everywhere else. Change the object, not all the callers manipulating the object.

So, for our UITableViewCell example above, the change is simple. First, hide the details how our table view cell is implemented:

MyTableViewCell.h

@interface MyTableViewCell: UITableViewCell
- (void)setLeftText:(NSString *)left rightText:(NSString *)right;
@end

MyTableViewCell.m

@implementation MyTableViewCell
@property (strong) IBOutlet UILabel *leftLabel;
@property (strong) IBOutlet UILabel *rightLabel;

- (void)setLeftText:(NSString *)left rightText:(NSString *)right
{
    self.leftLabel.text = left;
    self.rightLabel.text = right;
}
@end

And in our caller code:

MyTableViewController.m

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    MyTableViewCell *c = (MyTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"MyTableViewCell" forIndexPath:indexPath];

    c.leftLabel.text = [NSString stringWithFormat:@"Left %d",indexPath.row];
    c.rightLabel.text = @"Right Label";
    [c setLeftText:[NSString stringWithFormat:@"Left %d",indexPath.row]
         rightText:@"Right Label"];
 

    return c;
}

The original offending code was wrong because it confused the “how” to do something (setting the internal structure of the table cell) with the “what”: set the left and right text.

And notice that now we’ve hidden the details inside the table view. So later, if for some reason we change our implementation of the UITableViewCell:

MyTableViewCell.m

@implementation MyTableViewCell
@property (copy) NSString *leftLabel;
@property (copy) NSString UILabel *rightLabel;

- (void)setLeftText:(NSString *)left rightText:(NSString *)right
{
    self.leftLabel = left;
    self.rightLabel = right;
	[self setNeedsDisplay];
}

- (void)drawRect:(CGRect)r
{
    CGRect textRect = CGRectMake(10, 0, 146, 44);
    {
        NSString* textContent = self.leftLabel;
        UIFont* textFont = [UIFont fontWithName: @"HelveticaNeue-Light" size: UIFont.labelFontSize];
        [UIColor.blackColor setFill];
        [textContent drawInRect: CGRectOffset(textRect, 0, (CGRectGetHeight(textRect) - [textContent sizeWithFont: textFont constrainedToSize: textRect.size lineBreakMode: UILineBreakModeWordWrap].height) / 2) withFont: textFont lineBreakMode: UILineBreakModeWordWrap alignment: UITextAlignmentLeft];
    }

    CGRect text2Rect = CGRectMake(164, 0, 146, 44);
    {
        NSString* textContent = self.rightLabel;
        UIFont* text2Font = [UIFont fontWithName: @"HelveticaNeue-Light" size: UIFont.labelFontSize];
        [UIColor.blueColor setFill];
        [textContent drawInRect: CGRectOffset(text2Rect, 0, (CGRectGetHeight(text2Rect) - [textContent sizeWithFont: text2Font constrainedToSize: text2Rect.size lineBreakMode: UILineBreakModeWordWrap].height) / 2) withFont: text2Font lineBreakMode: UILineBreakModeWordWrap alignment: UITextAlignmentRight];
    }
}
@end

Notice that we don’t have to change a single thing in MyTableViewController.m, simply because it never knew how the table view drew itself; it only knew how to ask.

Objective C declaration shortcuts

With a recent update (okay, not quite so recent update) to Objective C, the following lexical shortcuts appear to have been added:

Create a dictionary using @{…}

The @{ … } shortcut has been added to create a new NSDictionary with a list of keys and values. The format appears to be:

@{ key : value , ... }

So, to create a new dictionary with three keys:

NSDictionary *d = @{ @"a": @"First",
                     @"b": @"Second",
                     @"c": @"Third" };

This creates a dictionary with three keys: @”a”, @”b” and @”c”, with the values @”First”, @”Second” and @”Third”, respectively.

Create an array using @[ … ]

The @[ … ] shortcut creates a new NSArray with a list of values. The format appears to be:

@[ value, value, ... }

So, to create a new array with three items:

NSArray *a = @[ @"a", @"b", @"c" ];

This creates an array with three items, @”a”, @”b” and @”c”.

Create an NSNumber wrapper around a numeric constant using @(…)

The @(…) appears to take a scalar and wrap it in an NSNumber object. Thus:

NSNumber *n = @( 5 );

creates a new NSNumber with the value 5.


You can combine each of these together in any way you wish. For example:

NSDictionary *d = @{ @(1): @[ @"A" ],
                     @(2): @[ @"Another", @"Thing" ],
                     @(3): @[ @"Tom", @"Dick", @"Harry" ] };

Far more convenient than the old way.


I’ve seen the first two documented elsewhere, but I don’t think I’ve seen the third one (boxing an NSNumber) mentioned anywhere, and I don’t quite remember where I saw it. Probably in the compiler release notes.

Also note that these can be used in-line with code and not just with constant objects. So, for example, you can use the NSNumber boxing mechanism to box an integer return value from a function:

NSNumber *count = @( [array count] );

This has been a public service announcement.

1 2 3 4 36