Wednesday, August 31, 2011

"Where can we take the customer?"

And, one of the things I’ve always found is that you’ve got to start with the customer experience and work backwards for the technology. You can’t start with the technology and try to figure out where you’re going to try to sell it. And I made this mistake probably more than anybody else in this room. And I got the scar tissue to prove it. And I know that it’s the case.

...

And as we have tried to come up with a strategy and a vision for Apple, it started with “What incredible benefits can we give to the customer? Where can we take the customer?” Not starting with “Let’s sit down with the engineers and figure out what awesome technology we have and then how are we going to market that?” And I think that’s the right path to take.

- Steve Jobs at WWDC 1997

 

Wednesday, August 3, 2011

Developing on Android vs iOS

If you're building mobile apps these days, you're probably watching the Android market closely if you're not already developing for it. With reports coming in weekly that Android activations are growing faster than ever, simple extrapolation will tell you that soon, there will be more Android devices on that planet than people. Many successful mobile devs, most of them currently focused on Apple's iOS platform, are seriously investigating the Android platform and starting to port their apps. A few adventurous developers have written some thoughtful articles describing their experience and comparing Android and iOS development.

Nick Farina of Spotlight Mobile describes his impressions of Android garnered while porting his Meridian app from iOS. He covers the good and the bad of each platform in technical detail, and it's a good read if you're a developer moving from iOS to Android or vice versa. Nick approaches Android with the open mind of a developer who has worked on many platforms—the first version of Meridian was launched on Windows Mobile. Nick sums up his philosophy:
We decided it was important to keep the native stuff native, and to respect each platform’s conventions as much as possible.
...
So, we rolled up our sleeves, downloaded the Android SDK, and got to work
Back in March, Geoffrey Goetz of GigaOM gave his comparison of development on the two platforms. Goetz gives a high level summary, including a somewhat shallow summary table highlighting the platform differences. This is probably most useful if you're an executive who manages mobile developers, but is worth a quick read if you're a developer who's new to one of the two platforms. Goetz mentions Apple's WWDC videos and the Stanford iOS development course on iTunesU as a big plus for the developer learning experience on iOS and I have to agree: both are excellent resources. Goetz fails to mention that videos of many Google IO sessions covering Android are also freely available, though I can't say if they have the same high quality as Apple's iTunesU offerings.

Samuel Sutch gives another iOS developer's perspective on Android in a post on Google+. He sums up his take on Android in the opening paragraph:
The Android API requires it's users be really good programmers. Android abstractions are much more in-depth, (drawn out, forced, and complicated) than the equivalent iOS abstractions. However "Intents" are great once you get them.
I also recommend the discussion of the post on Hacker News.

Finally, if you're thinking about jumping on the Android bandwagon, keep in mind Ben Duchac's post, Why My Mom Bought an Android, Returned It, and Got an iPhone. Android can be a challenging experience for non-technophiles. I suspect that because Apple has positioned the iPhone and iPad as premium devices, they've captured a large fraction of consumers who are interested and engaged in their mobile experience, and iOS app sales have benefitted from that. Conversely, non-techie Android owners are less interested in using their devices to the fullest and more sensitive to price.

If you want to make money on app sales, I wouldn't bet the farm on Android right now. If you're targeting a technophilic audience, you probably want to be on both Android and iOS. If you're pursuing app sales to a mass market, I would recommend iOS first and Android as an optional second right now. However, if you have an existing product or service with a supplemental mobile app, you should definitely be planning to offer it on both iOS and Android.

Tuesday, August 2, 2011

Objective-C Tuesdays: more about dynamic arrays

Welcome back to Objective-C Tuesdays. Last time we were talking about dynamic arrays in C and NSMutableArray in Objective-C. We'll continue looking at both today.

We looked at using malloc() or calloc() to dynamically allocate a block of memory that you can treat like an array. This is very useful when you don't know the number of items you need to store until run time or when you need the array to exist longer than the current function call.

But what happens when you need to grow or shrink the memory block? Well, the straightforward way would be to allocate a new memory block, copy over the contents and free the old block. You use the memcpy() function in the C standard library to do the copying.
// resizing a memory blockint *lotteryNumbers = malloc(sizeof(int) * 6);if ( ! lotteryNumbers) {  // memory allocation failed  exit(EXIT_FAILURE);}lotteryNumbers[0] = 7;// ...lotteryNumbers[5] = 29;// now we need to store more numbers// so allocate a bigger memory blockint *biggerMemoryBlock = malloc(sizeof(int) * 12);if ( ! biggerMemoryBlock) {  // memory allocation failed  exit(EXIT_FAILURE);}// copy lotteryNumbers into biggerMemoryBlockmemcpy(biggerMemoryBlock, lotteryNumbers, sizeof(int) * 6);// free old memory blockfree(lotteryNumbers);// replace old memory block pointer with new onelotteryNumbers = biggerMemoryBlock;lotteryNumbers[6] = 31;// ...lotteryNumbers[11] = 49;
When copying blocks of memory, be careful to specify the correct size in bytes. In the example above, we use the same expression to calculate the size, sizeof(int) * 6 for both the original call to malloc() and to memcpy(). Using the sizeof operator like this serves two purposes. It makes the code portable, since the size of an int may be different on some systems (it's four bytes on iOS). More importantly, it tells anyone reading the code that you intended to allocate six ints. If you had specified simply malloc(24) or even malloc(6 * 4), your intention is not as clear.

Resizing a memory block with realloc()
Allocating a larger or smaller memory block and copying over the contents works perfectly, but it is tedious. Fortunately, the C standard library includes the realloc() function which does exactly this for you in one function call. It can operate on any memory block allocated with malloc() or calloc(). In addition, because it's part of the standard library, realloc() can do things that you can't: it will try to grow or shrink the memory block in place, skipping the copy step. Sometimes the memory manager will give you a block of memory somewhat bigger than you requested, other times the memory area after your memory block is currently unused. Because realloc() is privy to the implementation details of the memory manager, it can figure out when it's safe to grow your memory block in place.

The realloc() function returns a pointer to either the original memory block or a new memory block on success, or NULL if memory allocation fails. If the new memory block is bigger than the original, the new items will be set to zero, just as if you allocated the memory block with calloc(). Like malloc(), realloc() requires you to calculate the size of the memory block in bytes.
// using realloc()int *lotteryNumbers = malloc(sizeof(int) * 2);if ( ! lotteryNumbers) {  // out of memory  exit(EXIT_FAILURE);}lotteryNumbers[0] = 7;lotteryNumbers[1] = 11;// ...int *resizedLotteryNumbers = realloc(lotteryNumbers, sizeof(int) * 6);if ( ! resizedLotteryNumbers) {  // out of memory but lotteryNumbers memory block  // is still valid and unchanged  exit(EXIT_FAILURE);}// replace the old pointer with the new onelotteryNumbers = resizedLotteryNumbers;lotteryNumbers[2] = 19;// ...
If realloc() fails, it leaves the original memory block unchanged. Just as for calloc() and malloc(), you must remember to call free() on the memory block when you're done with it.

Inserting items into a C array
It should be obvious by now how to add items to the end of a C array (if it's big enough) or a dynamically allocated memory block that you've enlarged using realloc(). But how do you insert an item at the beginning or middle of an array while keeping all of the current items? There's no magic here, you have to shift items to higher indices to make space for the new one.
// insert an item at the start of a C arrayint lotteryNumbers[6] = { 11, 17 }; // has room for six items// shift current items uplotteryNumbers[2] = lotteryNumbers[1];lotteryNumbers[1] = lotteryNumbers[0];// array now holds { 11, 11, 17 }lotteryNumbers[0] = 7; // insert new item// array now holds { 7, 11, 17 }
Note that you need to shift items starting at the end of the array, otherwise you'll overwrite items you want to preserve. Obviously writing a line of code for each item you need to shift isn't a practical solution. You might be tempted to use the memcpy() function to shift items, but memcpy() has an important restriction: the source and destination memory blocks may not overlap. (This is because memcpy() may copy items front to back and thus overwrite items you want to preserve.) The memmove() function is meant to be used when the memory blocks overlap and will always shift items in the correct order to preserve the contents.
// using memmove() to insert an itemint lotteryNumbers[6] = { 11, 17 }; // has room for six items// shift current items upint *destination = lotteryNumbers + 1;int *source = lotteryNumbers;size_t size = sizeof(int) * 2;memmove(destination, source, size);// array now holds { 11, 11, 17 }lotteryNumbers[0] = 7; // insert new item// array now holds { 7, 11, 17 }
Because memmove() can operate on any kind of array or memory block, we need to do some pointer arithmetic to determine the source and destination addresses and the number of bytes to move. Again, the sizeof operator helps make our intentions clear. An alternate way specify the source and destination addresses is to use the address of operator (&) on indexed items in the array.
// determine source and destination using address of// ...int *destination = &lotteryNumbers[1];int *source = &lotteryNumbers[0];size_t size = sizeof(int) * 2;memmove(destination, source, size);// array now holds { 11, 11, 17 }// ...
These are equivalent notations and choosing one over the other is a matter of style.

You can use this technique to insert items into both C arrays and dynamically allocated memory blocks. Just make sure that there is enough space to move items around and that you don't write items past the end of your array or memory. As with all things in C, there is no safety net. To remove items from the beginning or middle of an array, follow the same procedure using memmove(), only shift items down and intentionally overwrite the items you want to delete. I'll leave this one as an exercise for the reader ☺.

Inserting items into an NSMutableArray
While using memmove() to shift items around isn't too terrible, the equivalent operations using NSMutableArray are naturally much more direct. To insert a single item at a particular index, you naturally use -insertObject:atIndex:
// inserting an item into an NSMutableArrayNSMutableArray *colors = [NSMutableArray arrayWithObjects:@"red",                                                           @"green",                                                           @"blue",                                                           nil];[colors insertObject:@"orange" atIndex:1];// colors now holds "red", "orange", "green" and "blue"
Inserting multiple items at one time is trickier. With the -insertObjects:atIndexes: method, you can insert items from an NSArray into your NSMutableArray. The tricky part here is that you need to also pass in an NSIndexSet (or NSMutableIndexSet) along with the array. Here's how you would insert an NSArray containing one item.
// inserting an item into an NSMutableArrayNSMutableArray *colors = [NSMutableArray arrayWithObjects:@"red",                                                           @"green",                                                           @"blue",                                                           nil];NSArray *newColors = [NSArray arrayWithObject:@"orange"];NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:1];[colors insertObjects:newColors atIndexes:indexSet];// colors now holds "red", "orange", "green" and "blue"
You must make sure that there is an index in the NSIndexSet for each item you are inserting. If you want to insert the new items all in one spot, the +indexSetWithIndexesInRange: method of NSIndexSet makes this easy.
// inserting multiple items into an NSMutableArrayNSMutableArray *colors = [NSMutableArray arrayWithObjects:@"red",                                                           @"green",                                                           @"blue",                                                           nil];NSArray *rainbowColors = [NSArray arrayWithObjects:@"orange",                                                    @"yellow",                                                    @"indigo",                                                    @"violet",                                                    nil];NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 4)];[colors insertObjects:rainbowColors atIndexes:indexSet];// colors now holds "red", "orange", "yellow", "indigo", "violet", "green" and "blue"
Sometimes you want to insert different items at different points in your NSMutableArray. This is where -insertObjects:atIndexes: really shines. You'll want to use NSMutableIndexSet to create the index set in this case. Lets modify the previous example to insert the colors in standard rainbow order.
// inserting multiple items into an NSMutableArrayNSMutableArray *colors = [NSMutableArray arrayWithObjects:@"red",                                                           @"green",                                                           @"blue",                                                           nil];NSArray *rainbowColors = [NSArray arrayWithObjects:@"orange",                                                    @"yellow",                                                    @"indigo",                                                    @"violet",                                                    nil];NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSet];[indexSet addIndex:1];[indexSet addIndex:2];[indexSet addIndex:5];[indexSet addIndex:6];[colors insertObjects:rainbowColors atIndexes:indexSet];// colors now holds "red", "orange", "yellow", "green", "blue", "indigo" and "violet"
To figure out the correct indices can be tricky. Inside the -insertObjects:atIndexes: method, new items will be inserted one at a time, starting with the lowest index in the index set. While inserting a group of items is a very powerful capability of NSMutableArray, often times I think it's easier and faster to write correct code that uses -subarrayWithRange: to break the items up into contiguous blocks before inserting them, or even to use -insertObject:atIndex: repeatedly to insert items one by one. But when it is straightforward to figure out the index set, -insertObjects:atIndexes: makes your code very succinct.

Next time, we'll look at sorting C arrays, NSArrays and NSMutableArrays.

Tuesday, July 26, 2011

Objective-C Tuesdays: Dynamic arrays

Another week, another Objective-C Tuesdays. Last week we began our series on data structures with a look at arrays in C and the NSArray class. Both C arrays and NSArray objects have serious limitations: C arrays are fixed in size and NSArrays are immutable. Today we will look at overcoming those limitations.

Dynamically allocated memory
C arrays are fixed in size when they are declared:
int lotteryNumbers[6];
Here we declare an array that can hold six ints. We can freely change the six int values we store in the array, but we can't make the array larger or smaller once it's declared. But there's nothing really magical about arrays in C: in essence they're blocks of memory managed by the compiler. When we declare an array, we tell the compiler the number of items we need to store and the type of item and it calculates the number of bytes of memory it needs to set aside for the array. We can do the same thing with a dynamically allocated memory block. Let's dynamically allocate the same amount of storage using malloc():
// dynamically allocating an array
#include <stdlib.h>

int *lotteryNumbers = malloc(sizeof(int) * 6);
if (lotteryNumbers) {
  lotteryNumbers[0] = 7;
  lotteryNumbers[1] = 11;
  // ...
}
The malloc() function is part of the standard C library, and it allocates a memory block on the heap. As we saw last time, you can use the same square bracket index notation with an array variable or a pointer to a block of memory.

Unlike global variables (which persist for the whole life span of your program) and local variables (which live only as long as the current function call), you control the life span of memory you allocate on the heap. Just as you need to match -retain with -release in Objective-C, you need to match calls to malloc() with corresponding calls to free():
// always free dynamically allocating arrays
#include <stdlib.h>
// ...

int *lotteryNumbers = malloc(sizeof(int) * 6);

// use lotteryNumbers for a while...

free(lotteryNumbers);
The malloc() function takes one argument: the number of bytes to allocate. Since most useful items require more than one byte each, you need to use the sizeof() operator to get the size of the item type and multiply it by the number of items required.
// calculate the number of bytes required
// using the sizeof() operator
int *lotteryNumbers = malloc(sizeof(int) * 6);
if (lotteryNumbers) {
  // ...
The malloc() function returns a pointer to the newly allocated memory block on success. If malloc() fails, it returns NULL. You should always check the result of memory allocation and take appropriate action. The typical C idiom is to use the returned pointer as a boolean value, since NULL pointers in C evaluate to false while non-NULL pointers are true, similar to nil values in Objective-C.
// always test the returned pointer
int *lotteryNumbers = malloc(sizeof(int) * 6);
if (lotteryNumbers) {
  // okay to use...
} else {
  // we're out of memory...
}

Handling malloc() failures
If a call to malloc() fails and returns NULL, it's almost always because you've run out of available memory. There are two broad strategies for coping with a memory allocation failure: fail fast or abort the operation. In general, I recommend that you fail fast by doing something like this:
// fail fast when out of memory

int *lotteryNumbers = malloc(sizeof(int) * 6);
if ( ! lotteryNumbers) {
  fprintf(stderr, "%s:%i: Out of memory\n", __FILE__, __LINE__);
  exit(EXIT_FAILURE);
}
// okay to use memory
lotteryNumbers[0] = 7;
// ...
In an Objective-C program, you would use NSLog() instead of fprintf(). When small to medium size memory allocations fail, the system is seriously constrained and there's not much else your program can do to cope. In fact, iOS will likely terminate your app before you ever reach this condition.

Sometimes your program is trying to do something particularly memory intensive, like editing a large image or sound file. In cases like this, you should be prepared for large memory allocations to fail and try to abort the operation gracefully. The strategy in this case is to free all resources allocated for the operation so far and alert the user.

Using calloc() instead of malloc()
When you dynamically allocate a memory block, you frequently want to set all the items to zero. malloc() doesn't do any initialization to the memory block, so the initial contents are effectively random garbage. The calloc() function is similar to malloc(), but also clears the bytes in the memory block to zeros before returning.
// using calloc()
size_t itemCount = 6;
size_t itemSize = sizeof(int);
int *lotteryNumbers = calloc(itemCount, itemSize);
if (lotteryNumbers) {
  // okay to use...
Unlike malloc() which takes the size of the memory block in bytes, calloc() takes the number of items and the size of each item and does the math for you. Under the covers, calloc() allocates memory from the same heap that malloc() uses, so you need to call free() on the memory block when you're done.

There's a lot more to managing dynamically allocated memory blocks. We'll look at resizing a memory block using realloc() next time but for now let's move on to a more pleasant topic: NSMutableArray.

NSMutableArray
Like its immutable super class NSArray, the NSMutableArray class takes mutable array management to a higher level. You can create an NSMutableArray the same way you create an NSArray:
NSMutableArray *colors = [NSMutableArray arrayWithObjects:@"red", 
                                                          @"green", 
                                                          @"blue", 
                                                          nil];
Another common creation technique is to duplicate an existing immutable NSArray using the +arrayWithArray: or -initWithArray: methods.
NSArray *rgbColors = [NSArray arrayWithObjects:@"red", 
                                               @"green", 
                                               @"blue", 
                                               nil];
NSMutableArray *colors = [NSMutableArray arrayWithArray:rgbColors];
Often, you simply want an empty array to start with. The +array or -init methods from NSArray will do the trick here. (You can create empty immutable NSArray objects this way too, they're just usually not very useful.)

Adding items to the end of the array is easily done with -addObject: and -addObjectsFromArray:
NSMutableArray *colors = [NSMutableArray array];
// colors is empty

[colors addObject:@"yellow"];
[colors addObject:@"purple"];
// colors holds yellow, purple

NSArray *designerColors = [NSArray arrayWithObjects:@"mauve", 
                                                    @"chartreuse", 
                                                    @"seafoam", 
                                                    nil];
[colors addObjectsFromArray:designerColors];
// colors now holds yellow, purple, mauve, chartreuse and seafoam

NSMutableArray has many ways to remove objects. The -removeLastObject method is the inverse of -addObject:. The -removeObjectAtIndex: method removes an item at a particular index. Continuing with our array of colors:
// colors holds yellow, purple, mauve, chartreuse and seafoam
[colors removeLastObject];
// colors holds yellow, purple, mauve and chartreuse
[colors removeObjectAtIndex:0];
// colors holds purple, mauve and chartreuse

That covers the basics of adding and removing objects from an NSMutableArray. Next time, we'll cover more ways to manipulate the mutable array contents.

Wednesday, July 20, 2011

OS X Lion Internet Recovery

I just came across this page about Lion Recovery. I had read about the recovery partition earlier this morning in the excellent Ars Technica Lion review by John Siracusa, but new Macs have a feature called "Internet Recovery" that lets you automatically download a Lion recovery disk image from Apple's servers, even if you've wiped your hard drive:
If your Mac problem is a little less common — your hard drive has failed or you’ve installed a hard drive without OS X, for example — Internet Recovery takes over automatically. It downloads and starts Lion Recovery directly from Apple servers over a broadband Internet connection. And your Mac has access to the same Lion Recovery features online. Internet Recovery is built into every newly-released Mac starting with the Mac mini and MacBook Air.
This is one of those things that makes using a Mac so friction free. A big thumbs up to Apple for this feature.

Burning A Lion Boot Disc

If you're planning to install OS X Lion, but you want the safety and security of a physical install disk, or you prefer to wipe the hard drive and do a clean install, you can create your own bootable DVD installer using the Lion installer app from the Mac App Store and the Disk Utility application on your current Mac. Thomas Brand shows you how.

Forgotten C: The comma operator

Some good advice on the comma operator and when to use it from Jerry Ryle at MindTribe:
Comma operator?! Isn’t that thing just a separator? Nope. It’s occasionally an operator.
Read more about the rarely used comma operator in C. And MindTribe is looking to hire some great embedded developers.