Archive for the ‘iPhone’ Category

Editorial: Why Android Deserves Your Attention

I’ve read an increasing number of articles on the web recently from people who fervently believe that the Android platform is dead before it ever really got started. The common mantra going along with this is that Android is late to the party, and they didn’t bring anything new with them. First of all, I’m not sure how anyone getting into the game at this stage could be considered late, as the smartphone market is still quite infantile and rapidly developing…but I digress. Personally, I am very surprised by this perception, and have to wonder why the (mainly) iPhone community is so quick to attack?

I am a daily user of both the iPhone and Android platforms, and develop applications on both platforms as well. There are things about both that I love, and there are things about both that I hate; both as a user and developer.  I’m not the expert, and this is not an exhaustive comparison, but here are reasons that I believe Android deserves your attention (“you” being the developer) and why it is not dead…even if it doesn’t doesn’t immediately become king.

For context, as I’m writing this the latest software versions in the market are Android 2.1 and iPhone 3.1.2

The User Experience

There are some feature that Android provides to the user that the iPhone will need to incorporate eventually, in my opinion.  And I’m discussing them from a user perspective (not technical discussions of memory management, code efficiency, etc.)

  • Customizing Home Screen (Widgets)
    • The mobile user has severe A.D.D.; myself included. The faster the relevant content arrives to me, the less annoyed I am at how long I had to wait.  Checking the basics, like the Top 10 on my To-Do list or my next upcoming appointment, should not require me to run each application individually.  With Android, that data can live on my home screen in the form of widgets, and I can view it all right on the desktop (background services help a lot with this also, but we’ll get there).  And the data is REAL, it is not an image file stored and plastered as wallpaper.
  • Activity Stacking
    • My brain (and my life) works a LOT like a stack.  Often, what I am working on currently has something pushed on top of it that requires attention.  When I am done with that higher priority item, I need to step right back to doing what I was beforehand.  The Android concept of working follows this paradigm very well.  If I’m working in an application and need to send a quick email, I can bring email up on top of my current activity and do what I need to do.  After I am done with the email, I can go back to my previous activity and it is uninterrupted.  The same holds true if I get interrupted by a text message or other priority notification, I can load this activity ON TOP of what I was doing.  The tag line here is that I don’t have to close my old thoughts to start a new thought.

The Developer Experience

From the developer perspective, Android offers some neat opportunities as well.

  • Background Processing (Services)
    • Last year, when Apple announced that Push technology would be available to the iPhone, there was an uproar of excitement.  Suddenly, applications could grab the user’s attention without the need for the application to be running.  Push technology definitely has it’s place, but I do not believe that it can ever truly replace a background service in all instances.  Sometimes, developing a complete back-end server application and connecting with the Apple service is just too much overhead to put in to a project that just needs a method of notifying the user or doing simple work in the background.  Mobile devices may be resource constrained compared to the desktop platform, but I shouldn’t be afraid to run a few concurrent processes locally.  Shoot, I can do that on an 8-bit microcontroller.
  • System Modularity (Intents)
    • Intents embody the concept of inter-process communication and make it easy to modularize a system.  This architecture brings up a neat realization: once your app is using these to talk to itself, it’s a very small leap before apps start talking to each other.  This can be especially useful if you embrace the design philosophy that mobile apps should not have too many jobs, and that they should do 1-2 tasks efficiently.  Using an architecture based around Intents, complex tasks are now possible, while still holding true to the simplicity of each individual application.  This also provides great flexibility into way of hooking up with the core applications on the device (like mail and contacts) as just another module to your system.

I love my iPhone, and I love developing iPhone applications.  There are a lot of things on both the user and developer front that I prefer about Apple and the iPhone SDK.  I’ve chosen not to delve into them because so many people already have.  Any of the articles that I mentioned in the beginning spend a great deal of time touting the iPhone’s better features, so I’m just going to acknowledge (and agree) that they exist.  While these features alone may not skyrocket Google and cripple Apple, I believe that they are definitely enough to point out that Android has brought some new tricks to the party, and you probably ought to take notice.  I believe that they ARE enough to keep Apple from crippling Google straight out of the gate.

Adding Core Data Existing iPhone Projects

Core Data is a very powerful framework that Apple provides to developers for persisting data in their applications.  The primary advantage that is provided by Core Data is the ability to leverage efficient data storage technologies like SQLite, without forcing the developer to think in terms of query language; Core Data allows a developer to work with the data model in terms of objects.

There are many great books and articles on the proper use of Core Data; including Apple’s Core Data Tutorial.  The purpose of this article is simply to step the reader through adding the necessary piece to get Core Data into a previously created project; I defer to those other writings to describe the best techniques for Core Data use.

Apple has made the process of using Core Data in new projects very simple.  From the New Project… screen, many project templates include a checkbox titled Use Core Data for storage that tells Xcode to build the basics for Core Data into the project you create.  But what happens if you decide that Core Data’s advantages are going to help you, but you have already have your project set up in Xcode?  Where’s the button in the IDE to add Core Data to an existing project?

Below is a set of instructions on creating the context necessary to start using Core Data in your existing app.  In the code blocks, bold text is code that should already exist in your project.

Add the Missing Files

There are two files that must be added to your Xcode project in order to use Core Data; CoreData.framework and the .xcdatamodel

  • CoreData.framework
  1. From Xcode, control-click on the Frameworks folder inside the Groups & Files pane
  2. Select Add -> Existing Frameworks…
  3. Locate CoreData.framework, select it, and click the Add button
  • .xcdatamodel
  1. From Xcode, control-click on the Resources fold inside the Groups & Files pane
  2. Select Add -> New File…
  3. Select Resource from the iPhone OS group
  4. Select Data Model and click Next
  5. Give the file a name (the project name is a good choice) and click Next
  6. If your project does not have existing model classes that you would like to put into the data model, skip to step 7.  Otherwise, you may do so by selecting those classes on this screen and clicking Add to place them in the Selected Classes pane.
  7. Click Finish

Create the Missing Objects

Once all the necessary files are put into the project, the appropriate objects and methods need to be added to the application.

AppDelegate.h

Declare three new objects in the application delegate’s header file for the ManagedObjectModel, ManagedObjectContext, and PersistentStoreCoordinator. A convenience method, applicationDocumentsDirectory, is also defined to return the location of the application’s data files:

@interface AppDelegate : NSObject <UIApplicationDelegate> {
  NSManagedObjectModel *managedObjectModel;
  NSManagedObjectContext *managedObjectContext;
  NSPersistentStoreCoordinator *persistentStoreCoordinator;

  (...Existing Application Code...)
}

@property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;

- (NSString *)applicationDocumentsDirectory;

(...Existing Application Code...)
@end

AppDelegate.m

Implement applicationDocumentsDirectory, and explicitly write accessor methods for each new property as opposed to simply using the @synthesize keyword.  Note in the persistentStoreCoordinator accessor there is a location where you must name the SQLite file used for the store; this should most likely be your project name. Remember to properly release each object in dealloc:

@implementation AppDelegate
//Explicitly write Core Data accessors
- (NSManagedObjectContext *) managedObjectContext {
  if (managedObjectContext != nil) {
    return managedObjectContext;
  }
  NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
  if (coordinator != nil) {
    managedObjectContext = [[NSManagedObjectContext alloc] init];
    [managedObjectContext setPersistentStoreCoordinator: coordinator];
  }

  return managedObjectContext;
}

- (NSManagedObjectModel *)managedObjectModel {
  if (managedObjectModel != nil) {
    return managedObjectModel;
  }
  managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];

  return managedObjectModel;
}

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
  if (persistentStoreCoordinator != nil) {
    return persistentStoreCoordinator;
  }
  NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory]
                      stringByAppendingPathComponent: @"<Project Name>.sqlite"]];
  NSError *error = nil;
  persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc]
                                 initWithManagedObjectModel:[self managedObjectModel]];
  if(![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                 configuration:nil URL:storeUrl options:nil error:&error]) {
    /*Error for store creation should be handled in here*/
  }

  return persistentStoreCoordinator;
}

- (NSString *)applicationDocumentsDirectory {
  return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}

(...Existing Application Code...)

- (void)dealloc {
  [managedObjectContext release];
  [managedObjectModel release];
  [persistentStoreCoordinator release];

  (...Existing Dealloc Releases...)
}
@end

ViewController.h

The following code needs to be added to the interface of whatever view controller will interact with the Core Data objects.  The FetchedResultsController and another instance of the ManagedObjectContext:

@interface ViewController : UIViewController <NSFetchedResultsControllerDelegate> {
  NSFetchedResultsController *fetchedResultsController;
  NSManagedObjectContext *managedObjectContext;

(...Existing Application Code...)
}

@property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;
@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
@end

ViewController.m

Don’t forget to synthesize the new properties for their accessor methods:

@implementation ViewController
@synthesize fetchedResultsController, managedObjectContext;

(...Existing Application Code...)
@end

Add Links and Use Core Data

The managedObjectContext object has now been created as a property in both the AppDelegate and ViewController classes.  The declaration of managedObjectContext in the ViewController must reference the AppDelegate, which is the only place that object should be allocated.  Something like

ViewController.managedObjectContext = self.managedObjectContext;

should exist in the applicationDidFinishLaunching method of the AppDelegate to accomplish this.

Conclusion

Your project should now include all the necessary objects to perform Core Data operations within the application.  You can create the data model using Xcode’s built-in editor to define entities, properties, and relationships.  Then, work with the Core Data framework to store and fetch your persisted object data.