Using NSNotificationCenter to Facilitate Event Handling From Inside a UITableView

Something that really impressed me as I started learning iOS development and Objective-C is how easy it is to communicate between classes. One great way to do this is by using NSNotificationCenter. I use NSNotificationCenter a lot, and one place it’s been especially useful is event handling for buttons inside the cells of a UITableView. This post will first discuss using NSNotificationCenter as a way to implement event handling inside a table and has code examples in the bottom half of the article. It’s simple to implement as there’s just three pieces of code one needs to use to get a notification working.

In one of the projects I work on, we have a multi section table where each section represents a subset of all possible options. Each section has a header (which is an instance of a custom UITableViewCell, HeaderCell) with buttons on it for the user to tap to perform many functions such as selecting items included in that section, renaming and deleting the section, etc. The first thought  a new iOS developer may have is that all the event handling for the buttons being pressed should be in the HeaderCell class. That turns out to be tricky, because the HeaderCell is not providing its own data, nor can it directly trigger a refresh of the contents of the table. There is a UITableView data provider, which is the ViewController which is responsible for the view containing the UITableView. It would be possible to build public facing variables or functions to the ViewController to allow the HeaderCell to handle its events directly by modifying the data structures inside the ViewController, but this gets messy and isn’t ideal. It’s much better to have the ViewController manage all of the table data exclusively.

Instead, the thing to do is post a notification to NSNotificationCenter when one of the buttons in the HeaderCell is pressed. The ViewController then receives this notification, along with the object that sent it, allowing it to handle updating any data and UI being affected by the event, all  while maintaining complete control over its data.

Here’s an image of the top of one section of the UITableView. The HeaderCell is the area with a green background. To handle the buttons being pressed inside the HeaderCell, we use NSNotificationCenter.

 

To implement the HeaderCell’s role in the event handling, it simply needs to post a notification when a button was pressed. This is done with the function below contained inside the HeaderCell class. Remember to link the button with this function in Interface Builder.

-(IBAction) gearPressed:(id)sender{

    NSLog(@”Gear Pressed”);

    [[NSNotificationCenter defaultCenter] 

        postNotificationName:@”GearButtonPressedNotification” 

        object:self];

}

The ViewController requires two pieces of code to complete its role in this event handling. First it needs to be “listening” for the notification, aka being an observer of the notification. This is done before any notifications have been posted, so I always put the following inside the viewDidLoad function:

   [[NSNotificationCenter defaultCenter] addObserver:self
                                            selector:@selector(gearButtonPressed:)
                                                name:@”GearButtonPressedNotification”
                                              object:nil];

Notice two things about this:
1) The “name” provided matches exactly the string used by the HeaderCell for postNotificationName. If these two are not the same, the message will not be received.

2) the “selector” indicates what function will be called when the notification is received.

Which brings us to the last section of implementing event handling via NSNotificationCenter, doing the actual updates to our data! The following function is contained in the ViewController class as well. This is where I finally update the affected data and UI.

– (void) gearButtonPressed:(NSNotification *)note {
   NSLog(@”received gearpressed event”);

   NSIndexPath *selectedPath =

        [dataTableView indexPathForCell:(HeaderCell*)(note.object)];

    NSLog(@”%d”,selectedPath.section);

   …
}

In the gearButtonPressed function, the first thing to do is figure out which section sent the notification, because it indicates what data needs to change or where a UI element needs to be drawn. The details of what my program does when this event is detected isn’t relevant to this tutorial, but it is important to see how easy it is to determine which element of the table sent the notification.

Hopefully this post gave you insight into one of the great features of Objective-C and iOS development, simple message passing between classes. If you follow the structure laid out in this article, you’ll be able to maintain good MVC practices and keep the scope of data access to the controller class.

Tags: , , ,

Leave a Reply