On the iPhone, persistence is
golden. When starting or resuming your application from termination or
interruption, always return users to a state that closely matches where
they left off. This lets your users pick up with whatever tasks they
were involved with and provides a user interface that matches the
previous session. Recipe 1 introduces an example of doing exactly that.
This recipe stores both the current tab order and
the currently selected tab, and does so whenever those items are
updated. When a user launches the application, the code searches for
previous settings and applies them when they are found.
The approach used here depends on two delegate methods. The first, tabBarController:didEndCustomizingViewControllers:
provides the current array of view controllers after the user has
customized them with the More > Edit screen. This code snags their
titles (10%, 20%, and so on) and uses that information to relate a name
to each view controller.
The second delegate method is tabBarController: didSelectViewController:. The tab bar controller sends this method each time a user selects a new tab. By capturing the selectedIndex, this code stores the controller number relative to the current array.
Setting these values depends on using the iPhone’s built-in user defaults system, NSUserDefaults. This preferences system works very much as a large mutable dictionary. You can set values for keys using setObject: forKey:
[[NSUserDefaults standardUserDefaults] setObject:titles
forKey:@"tabOrder"];
and retrieve them with objectForKey:.
NSArray *titles = [[NSUserDefaults standardUserDefaults]
objectForKey:@"tabOrder"];
Always make sure to synchronize your
settings as shown in this code to ensure that the defaults dictionary
matches your changes. If you do not synchronize, the defaults will not
get set until the program terminates. If you do synchronize, your
changes are updated immediately. Any other parts of your application
that rely on checking these settings will then be guaranteed to access
the latest values.
When the application launches, it checks for
previous settings for the last selected tab order and selected tab. If
it finds them, it uses these to set up the tabs and select a tab to make
active. Since the titles contain the information about what brightness
value to show, this code converts the stored title from text to a number
and divides that number by ten to send to the initialization function.
Most applications aren’t based on such a simple
numeric system. Should you use titles to store your tab bar order, make
sure you name your view controllers meaningfully and in a way that lets
you match a view controller with the tab ordering.
Recipe 1. Storing Tab State to User Defaults
@implementation TestBedAppDelegate
- (void)tabBarController:(UITabBarController *)tabBarController
didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed
{
// Store the titles from the tabs in order
NSMutableArray *titles = [NSMutableArray array];
for (UIViewController *vc in viewControllers) [titles
addObject:vc.title];
[[NSUserDefaults standardUserDefaults] setObject:titles
forKey:@"tabOrder"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)tabBarController:(UITabBarController *)tabBarController
didSelectViewController:(UIViewController *)viewController
{
// Update the currently selected tab number
NSNumber *tabNumber = [NSNumber numberWithInt:[tabBarController
selectedIndex]];
[[NSUserDefaults standardUserDefaults] setObject:tabNumber
forKey:@"selectedTab"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)applicationDidFinishLaunching:(UIApplication *)application {
NSMutableArray *controllers = [NSMutableArray array];
NSArray *titles = [[NSUserDefaults standardUserDefaults]
objectForKey:@"tabOrder"];
if (titles)
{
// titles retrieved from user defaults
for (NSString *theTitle in titles)
{
BrightnessController *bControl = [[BrightnessController
alloc] initWithBrightness:([theTitle intValue] / 10)];
UINavigationController *nav = [[UINavigationController
alloc] initWithRootViewController:bControl];
nav.navigationBar.barStyle = UIBarStyleBlackTranslucent;
[bControl release];
[controllers addObject:nav];
[nav release];
}
} else {
// generate all new controllers
for (int i = 0; i <= 10; i++)
{
BrightnessController *bControl = [[BrightnessController
alloc] initWithBrightness:i];
UINavigationController *nav = [[UINavigationController
alloc] initWithRootViewController:bControl];
nav.navigationBar.barStyle = UIBarStyleBlackTranslucent;
[bControl release];
[controllers addObject:nav];
[nav release];
}
}
// Create the toolbar and add the view controllers
UITabBarController *tbarController = [[UITabBarController alloc]
init];
tbarController.viewControllers = controllers;
tbarController.customizableViewControllers = controllers;
tbarController.delegate = self;
NSNumber *tabNumber = [[NSUserDefaults standardUserDefaults]
objectForKey:@"selectedTab"];
if (tabNumber)
tbarController.selectedIndex = [tabNumber intValue];
// Set up the window
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen
mainScreen] bounds]];
[window addSubview:tbarController.view];
[window makeKeyAndVisible];
}
@end
|