The framework knows when it needs to see the content of your view so you don’t have to worry about it… the system is very efficient at this process to minimize the work that has to done and the it even caches the results so drawRect doesn’t have be called multiple times (this is especially good for things like animation). If you feel like you are at a state in your controller where you want call drawRect… you should instead call setNeedsDisplay on the view and the system will take care of calling drawRect when the time is right. In fact… if you do call drawRect… nothing is going to change on the screen so just don’t do it (your app might even crash!). This fits in with one the main themes in iPhone developement… laziness is good. This lazy way of updating the view lets the framework optimize the hard-work that comes along with rendering to the screen.

It has been a little while since my last post… I have been spending my time picking up Ruby on Rails so that I could create a web-service for my upcoming iPhone app… I’ll post about that shortly. But first a quick comment about views.

I have seen a lot of people who are starting out with iPhone dev get confused about how the process or creating and loading views. Take a look at this code from this code:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Navigation logic -- create and push a new view controller
    if(childController == nil)
        childController = [[BookDetailViewController alloc] initWithNibName:@"BookDetailView" bundle:[NSBundle mainBundle]];

    Book *selectedBook = [appDelegate.books objectAtIndex:indexPath.row];
    childController .book = selectedBook ;

    [self.navigationController pushViewController:childController animated:YES];
}

If you want to do something like set the title of the childController with the title of the Book… do not do it in the viewDidLoad or awakeFromNib methods. These are called only 1 time in this instance because the child controller is only created once. Those methods are typically for setting up the controller’s “general state.” What I mean by “general” is the data that is not going to change from different book to book (like the background color and font and everything). Do not use this method to set up specific state for each book. A much better implementation would be to override the setBook method and do any extra initialization there. That way, everytime you have a new book, you will update the other values:

-(void) setBook(Book*)newBook {
    if(book != newBook){
        [book release];
        book = [newBook retain];
        self.title = book.title;
    }
}

Hope this Helps!

I have been working on my BusTracker application and have recently added the ability to view upcoming bus arrival times for a specific stop. The way it works is that a user presses the “Routes” tab and is presented with a list all Bus Routes in the system (notice I used the word “presses” and not “clicked”… there is no mouse on the iPhone!!!). The user can select a route, then select a direction, then select the bus stop they are at… and then they are presented with a list of upcoming bus arrival times for that specific stop. Immediately, I had a design in my head that consisted of an abstract controller and simple controllers for each page. Each page’s controller would inherit from the abstract controller and build off of that basic functionality (they all look the same… they just present different data). This is how I would do it if I were doing something in Spring MVC… so it should be okay here was well!

It turns out that after doing some more reading on Objective C that it doesn’t even have the reserved word “abstract”… here’s what Apple says about it:

Abstract Classes

Some classes are designed only or primarily so that other classes can inherit from them. These abstract classes group methods and instance variables that can be used by a number of different subclasses into a common definition. The abstract class is typically incomplete by itself, but contains useful code that reduces the implementation burden of its subclasses. (Because abstract classes must have subclasses to be useful, they’re sometimes also called abstract superclasses.)

Unlike some other languages, Objective-C does not have syntax to mark classes as abstract, nor does it prevent you from creating an instance of an abstract class.

The NSObject class is the canonical example of an abstract class in Cocoa. You never use instances of the NSObject class in an application—it wouldn’t be good for anything; it would be a generic object with the ability to do nothing in particular.

The NSView class, on the other hand, provides an example of an abstract class instances of which you might occasionally use directly.

Abstract classes often contain code that helps define the structure of an application. When you create subclasses of these classes, instances of your new classes fit effortlessly into the application structure and work automatically with other objects.

The language is much more tailored to delegation and composition rather than inheritance. Instead of having an abstract controller with other controllers inheriting from that… I chose to go with 1 simple concrete controller that calls a delegate when it needs a specific implementation. So, each page will use a different instance of the same controller that delegates to an object that knows how to present info for that page. This approach is also more easily tested because I don’t have to set up all of the data needed to test an entire controller… I only have to setup what the delegate needs to handle its specific task. I’ll post some sample code later on and link it to this post.

In a previous post I went over the process of creating a favorites view similar to the Phone app on the iPhone. While the concepts discussed in that post are important if you want to do iPhone development, I found a short-cut for creating the edit button while I was digging through the UIViewController api.

In the last post, when the user clicked on the “Edit” button the “editClicked” method was called:

-(IBAction) editClicked:(id)sender {
	[self.myTableView setEditing:YES animated:YES];
	UIBarButtonItem *doneButton =
		[[UIBarButtonItem alloc]
		   initWithBarButtonSystemItem:UIBarButtonSystemItemDone
		   target:self
		   action:@selector(doneEditingTable)];
	navItem.leftBarButtonItem  = doneButton;
	navItem.rightBarButtonItem = nil;
	[doneButton release];
}

As you can see… first we set the editing mode, then created a new “Done” button to replace the the “Edit” button. I can get rid of this code if I set the “Edit” button to the editButtonItem object of my controller. This built-in button item will toggle its title and associated state between Edit and Done when it is pressed. Plus, the default button action invokes the setEditing:animated: method. That takes care of most of the code in the editClicked method. All I need to do to is implement the setEditing:animated:, then show/hide the “+” button based on the editing mode… simple and easy!

Last week I wrote about an error I got when I added a property to a Managed Object. I posted the solution, but was unable to dig into the docs and understand what was really happening.

It turns out that Apple (as usual) has provided a great resource for understanding the data migration process. It goes over simple and advanced migrations… but for my purposes, the simple-way was all the I needed. Core Data can perform automatic “lightweight migration” which means it infers differences between the original and updated managed object models. You don’t have create a new version of the mapping model! This is especially good while you are in development because you don’t have to reload all of your test data each time you change the data model each time.

The only catch is that lightweight migration will only work if your changes meet certain criteria:

  • Simple addition of a new attribute
  • A non-optional attribute becoming optional
  • An optional attribute becoming non-optional, and defining a default value

Anything that doesn’t fit this criteria will have to be done manually… which is also in the docs!

I got this error last night after going through the Core Data Tutorial on the Apple dev site. I completed the tutorial and everything worked fine… then I added a few more things to the UI and a new field to the Event Managed Object. When I tried to re-build and run, I got that error above (“NSInternalInconsistencyException: This NSPersistentStoreCoordinator has no persistent stores. It cannot perform a save operation”) when trying to save an Event.

After doing some research, it turns out that I need to explicitly tell NSPersistentStoreCoordinator to automatically migrate newer versions of the data objects. I had to set these 2 values and pass them into the NSPersistentStoreCoordinator as options when it is created:

NSDictionary *options =
    [NSDictionary dictionaryWithObjectsAndKeys:
        [NSNumber numberWithBool:YES],
            NSMigratePersistentStoresAutomaticallyOption,
        [NSNumber numberWithBool:YES],
            NSInferMappingModelAutomaticallyOption, nil];

persistentStoreCoordinator =
    [[NSPersistentStoreCoordinator alloc]
        initWithManagedObjectModel:[self managedObjectModel]];

if (![persistentStoreCoordinator
        addPersistentStoreWithType:NSSQLiteStoreType
        configuration:nil URL:storeUrl options:options error:&error]) {
        // Handle error if failure
}

I’ll update this post as I understand more about what is going on…

This will be the first simple tutorial covering some of the new things I am tackling as I build my first iPhone app. Today I want to go over creating a table view that will show a list of favorites that the user has already selected; this will basically mimic the “Favorites” Tab in the Phone app. I am going to keep this one simple, so there will be no adding of Favorites this time… that can be for another time.

Here is what we want to accomplish(with Editing mode on the right):

On to the code… lets start out by looking at the FavoritesViewController.h:

@interface FavoritesViewController : UIViewController <UITableViewDataSource> {
	NSMutableArray *favorites;
	UITableView *myTableView;
	UINavigationItem *navItem;
	UIBarButtonItem *editButton;
	UIBarButtonItem *addButton;
}

@property(nonatomic,retain) IBOutlet UIBarButtonItem *addButton;
@property(nonatomic,retain) IBOutlet UIBarButtonItem *editButton;
@property(nonatomic,retain) IBOutlet UINavigationItem *navItem;
@property(nonatomic,retain) IBOutlet UITableView *myTableView;
@property(nonatomic,retain) NSMutableArray *favorites;

-(IBAction) addClicked:(id)sender;
-(IBAction) editClicked:(id)sender;
@end

The ‘favorites’ array is the DataSource for the myTableView object. The navItem is the bar at the top of the screen that shows our “Favorites” label and holds the editButton and addButton; I made these IBOutlets so I could set them in Interface Builder. The 2 IBActions will fire when their respective buttons are pressed… lets focus on the editClicked method. When the user presses the Edit button, we want to tell the TableView to go into editing-mode and then update the buttons to show their correct state.

-(IBAction) editClicked:(id)sender {
	[self.myTableView setEditing:YES animated:YES];
	UIBarButtonItem *doneButton =
		[[UIBarButtonItem alloc]
		   initWithBarButtonSystemItem:UIBarButtonSystemItemDone
		   target:self
		   action:@selector(doneEditingTable)];
	navItem.leftBarButtonItem  = doneButton;
	navItem.rightBarButtonItem = nil;
	[doneButton release];
}

Pretty simple stuff right!… When the User presses the newly created “Done” button, the doneEditingTable method will fire so we can deal with the clean up. Before that happens though, the user will probably want to actually delete a row. The framework will handle all of the animation that happens when the user presses the little circle to the left of the text. UPDATE: I found an easier implementation for the Edit/Done button… check out my short post.

After the “Delete” button is hit, the commitEditingStyle method is called so you will need to override it:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

	if (editingStyle == UITableViewCellEditingStyleDelete) {
		UserDataService *dataService = [(BusTrackerAppDelegate*)[UIApplication sharedApplication].delegate userDataService];

		FavoriteStop *favorite = [favorites objectAtIndex:indexPath.row];
		[dataService deleteFavorite:favorite];

		// Update the array and table view.
		[favorites removeObjectAtIndex:indexPath.row];
		[self.myTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
	}
}

As you can see, first I need to delete the FavoriteStop object from my db via my UserDataService. After the service method successfully finishes the deletion, the TableView needs to be updated to reflect the new list of favorites. Instead of reloading all of the data for the list, you can just delete the corresponding row from the table’s data source and TableView. When the user is ready to finish deleting, they hit the “Done” button which fires an action to the doneEditingTable method. The only thing left to do in order to get back to the “Normal” state (like when the view first loaded) is to reset the buttons.

- (void) doneEditingTable {
	[self.myTableView setEditing:NO animated:YES];
	navItem.leftBarButtonItem  = editButton;
	navItem.rightBarButtonItem = addButton;
}

I had to keep a reference to the original buttons on top because they were removed earlier, so I made sure to connect them in Interface Builder (see the interface editButton/addButton outlets). After that method finishes, the user is back to the original view… you are done!

Finally, if you want to add sorting to the edit view you only need to overload a few more methods:

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
        // if you want to prevent a specific row from moving
	if (indexPath.row == 0) {
	    	return NO;
	}
	return YES;
}

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
	FavoriteStop *favorite = [[self.myTableView objectAtIndex:sourceIndexPath.row]];
        // update sort order in db
        // ...........
	[self.myTableView removeObjectAtIndex:sourceIndexPath.row];
	[self.myTableView insertObject:favorite atIndex:destinationIndexPath.row];
}

There are more advanced ways to do this stuff, so check out the great doc on the apple dev site.

On accident, I accomplished something I had been trying to do for a while now: listen to a video-cast with the iphone asleep.  I believe 3.0 sdk update took away that feature and I have always wanted it to come back so I could save battery life.  I usually download news shows and watch/listen to them on the way to work.  The old way was easy… start the video-cast, then press the “Sleep/Wake” button and the audio would keep playing.  If you try that with the 3.0 sdk, the audio stops playing when you push the Sleep button.  In order to get it playing again… you need to push the microphone button on the iphone ear-buds (kind of like the same way you restart itunes)!

Boom!!!

Nib files (.xib) are Interface Builder User Interface Resources files used to describe the View portion of a Cocoa application (os x, iphone).  It isn’t too difficult to learn how to use Interface Builder (IB), but there are a few important things to know about Nibs before jumping into the mess.  At design time in IB you can layout user interface controls, add controller objects, and define connections between those controllers and the UI.  When you save your Nib, IB will archive those objects.  At runtime, the objects are unarchived with same values as you set within IB.

One simple but important thing to remember is to make sure you break up your UI into multiple Nib files.  You CAN put everything you want into 1 Nib file… TableViewController1 -> TableViewController2 -> TableViewController3 -> DetailsController… but even if you CAN do something, it doesn’t mean you SHOULD.  If you have a Nib file that contains a lot of objects it is going to cause your application to load ALL of those objects when the Nib is loaded.  For instance… in the example I had before, lets say you only wanted to load the TableViewController1 and show its data (when the user selects a row in Table1, you then want to load Table2).  If you have everything in 1 Nib file then your app is going to call  [TableViewController1 viewDidLoad], [TableViewController2 viewDidLoad], [TableViewController3 viewDidLoad], and [DetailsController viewDidLoad]… all because the framework is loading each object into memory.

If you are developing for the iphone, you probably don’t want to use up that memory when you have no idea whether or not the user will even click through to the DetailsController.  If you separate your that big Nib file into multiple files you will be able to preserve the lazy loading functionality of the framework and save yourself headaches in the future.

I have been wanting to dive into developing and deploying a real iPhone application but have had a hard time deciding on what type of app to make.  I recently came across an article talking about the CTA developing a web services API that will allow developers the ability to access all GPS data and arrival times for the buses in the system.  This seemed like it would be a great candidate to use in an iPhone app because it would consist of getting data from web services, saving user data locally, using the maps api, displaying different views and controls, and parsing xml into objects… plus… it is an app I can actually use since I ride the bus a ton during the winter.  In the next few days I’ll be posting my experience as I build this app… I’ll try and throw in some tutorials as I go along.