ios state preservation and restoration
DESCRIPTION
Covers iOS app state preservation and restoration with extra emphasis on NSCoding. WWCD 2012 session 208 glosses over some of the fine details of how NSCoding works. Understanding this foundation better helps in understanding state preservation and restoration.TRANSCRIPT
iOS State Preservation and RestorationRobert BrownTwitter: @robby_brownapp.net: @robert_brown
What is State Restoration?
Restores your app where the user left it
Makes your apps appear as if they never terminated
Lets users seamlessly get back to what they want
NSCoding
Similar to writing to a plist
Any object that conforms to NSCoding can be encoded
plist NSCodingNSNumber Y YNSString Y Y
NSDictionary Y YNSArray Y YNSData Y YNSDate Y YNSSet N YBlocks N N
Anything Else N Y
NSCoding
-initWithCoder:
-decodeObjectForKey:
-encodeWithCoder:
-encodeObject:forKey:
NSSecureCoding
Irrelevant to state restoration, but nice to know
Securely persists data
Many Cocoa classes conform to NSSecureCoding
Restoration Identifiers
Each view controller you want to restore must define a restoration identifier
Restoration identifiers make up a restoration ID path
Restoration paths must be unique
Example: /TabBarController/AboutViewController
Restoration Identifiers/A
/A/C/A/B/A/B
/A/C/B
Preservation Flow
-application:shouldSaveApplicationState:
-application:willEncodeRestorableStateWithCoder:
Each window on main screen Save view controller Save view
1
2
3 4
5
Preservation Flow
- (void)encodeRestorableStateWithCoder:(NSCoder *)coder {
[super encodeRestorableStateWithCoder:coder];
// Assumes Person is NSCoding-compliant
[coder encodeObject:self.person forKey:@“person”];
}
Restoration Flow-application:willFinishLaunchingWithOptions:
-application:shouldRestoreApplicationState:
-application:didFinishLaunchingWithOptions:
State Restoration
Yes
No
-application:didDecodeRestorableState:withCoder:
Restoration Flow
Each view controller +viewControllerWithRestorationIdentifierPath:coder:
Found view controllers
-decodeRestorableStateWithCoder:
Restore view controller state Restore view
1
3
4
5
2
Restoration Flow
+viewControllerWithRestorationIdentifierPath:(NSArray *) components coder:(NSCoder *)coder {
// Restore only what you absolutely need
// You may not be able to restore other view controllers
return [self new];
}
Restoration Flow
- (void)decodeRestorableStateWithCoder:(NSCoder *)coder {
[super decodeRestorableStateWithCoder:coder];
self.person = [coder decodeObjectForKey:@“person”];
}
UIDataSourceModelAssociation
Many views will automatically restore their state
UITableView and UICollectionView need some extra help to restore your visible and selected cells
UIDataSourceModel association provides a mapping of cells to model objects
This is NOT intended to be used to persist data
UIDataSourceModelAssociation
-modelIdentifierForElementAtIndexPath:inView:
Converts from model object to ID
-indexPathForElementWithModelIdentifier:inView:
Converts from ID to model object
UIDataSourceModelAssociation
- (NSString*)modelIdentifierForElementAtIndexPath:(NSIndexPath *)idx inView:(UIView *)view {
// Uses Core Data
Person * person = self.persons[idx.row];
return person.objectID.URIRepresentation.absoluteString;
}
UIDataSourceModelAssociation
- (NSIndexPath *)indexPathForElementWithModelIdentifier:(NSString *)identifier inView:(UIView *)view {
NSURL * uri = [NSURL urlWithString:identifier];
NSPersistentStoreCoordinator * coordinator = // Your coordinator
NSManagedObjectContext * context = // Your context
NSManagedObjectID * objectID = [coordinator managedObjectIDForURIRepresentation:uri];
Person * person = [context existingObjectWithID:objectID error:NULL];
NSInteger index = [self.persons indexOfObject:person];
return [NSIndexPath indexPathForRow:index inSection:0];
}
Demo
Must use proper UIViewController containment
Restoration identifier paths must be unique
For a view controller to be restored, it must have a path to the root view controller
Manually terminating the app will delete the state
Gotchas
Gotchas
Restore only minimal state in +viewControllerWithRestorationIdentifierPath:
If a view controller that was persisted is not restored, the app delegate is given a chance to restore it
Testing state restoration isn’t straightforward
Press home button, then have Xcode kill the app
Gotchas
Restoration classes must conform to the UIViewControllerRestoration protocol
Restoration classes aren’t necessary when using UIStoryboard
Gotchas
If you change your view controller hierarchy, make sure you don’t restore from an older state
If your app crashes during restoration, the state data is thrown out
Want to Learn More?
WWDC Session 208
Archives and Serializations Programming Guide
iOS App Programming Guide
Questions?