OverridingDefaultActions Document
Overriding Default Actions
Overview
The CalendarStore framework provides UI classes and low-level model classes. The UI classes provide a rich and complete store experience to the user, while the model classes allows apps to build their own UI.
However, often apps only want to change some small part of the UI. It wouldn’t make much sense to re-implement the whole UI from scratch to accomplish that. For that, all UI classes implement the pageItemHandlerDelegate
, to allow apps to override specific behavior only.
Default PageItem actions
The UI classes (CalStoreCalendarStoreViewController, CalStoreStyledPageViewController, etc) all perform specific actions when the user interact when a CalStorePageItem object via their UI.
For example, CalStoreCalendarViewController will start installing a calendar via EventKit when the user taps on an already purchases item. CalStoreStyledPageViewController does the same, only presenting different UI.
Overriding PageItem actions
Every UI class that interacts with CalStorePageItem’s, does have a pageItemHandlerDelegate
. Delegates should conform to the formal protocol CalStorePageItemHandlerDelegate. This delegate object will receive various callbacks when a user interacts with a page-item and allows the delegate to override and stop the default behavior of the action, dynamically by returning NO
for the should* methods. Returning YES
or not implementing it, will ensure the default action will be performed.
Example: Overriding installation behavior
If you have an app that doesn’t want to use EventKit for installing calendars, you can still use the provided UI classes and override the installation process. The following sample code will show how to accomplish this:
@class SomeViewController () CalStorePageItemHandlerDelegate
@end
@implementation SomeViewController
-(void)launchCalendarStore
{
CalStoreCalendarViewController* vc = [CalStoreCalendarStoreViewController calendarStoreViewController];
vc.pageItemHandlerDelegate = self;
[self presentViewController:vc animated:YES completion:nil];
}
-(BOOL)shouldInstallCalendarForItem:(CalStorePageItemCalendar*)pageItem
withCallback:(CalStorePageItemHandlerDelegateCallback)showViewControllerCallback
{
// NOTE: in general, it's a good idea to provide some 'progress' feedback UI
// to the user, either with the help of showViewControllerCallback() our other means.
// let the framework create a unique url for our subscription
[pageItem createUrlWithCompletionHandler:^(NSURL* url, NSError* error){
// if we got an url, let our internal engine subscribe to the calendar
if[(url != nil)
[[OurInternalICSEngine sharedEngine] addSubscribedCalendarWithUrl:url];
else
NSLog(@"Error when requesting url for pageItem (%@): %@", pageItem, url); // we should also show the error to the user
}];
// we override this behavior, so return NO to indicate the default behavior should not be performed
return NO;
}
@end
Presenting Custom ViewControllers
Each method of the CalStorePageItemHandlerDelegate protocol has a showViewControllerCallback parameter. This parameter is a block that takes one UIViewController* object. If you want to show a custom view controller for some action, you should call this block with your view controller as parameter: presentViewController(vc)
.
Be aware that, one calling showViewControllerCallback, the delegate method shouldShowViewController:forItem:withCallback:
won’t be invoked; it will only be invoked by default actions, not overriden behavior.
The following sample code will show how to let the UI classes show custom view controllers.
@class SomeViewController () CalStorePageItemHandlerDelegate
@end
@implementation SomeViewController
-(void)launchCalendarStore
{
CalStoreCalendarViewController* vc = [CalStoreCalendarStoreViewController calendarStoreViewController];
vc.pageItemHandlerDelegate = self;
[self presentViewController:vc animated:YES completion:nil];
}
-(BOOL)shouldNavigateToWeatherForItem:(CalStorePageItemParameterizedCalendar*)pageItem
withCallback:(CalStorePageItemHandlerDelegateCallback)showViewControllerCallback;
{
// create our custom weather view controller
MyCustomWeatherViewController* vc = [[MyCustomWeatherViewController alloc] init];
vc.pageItem = pageItem;
// let the UI class present/push it
showViewControllerCallback(vc);
// we override this behavior, so return NO to indicate the default behavior should not be performed
return NO;
}
@end
Showing custom Intro Walkthrough
The Intro Walkthrough can be provided with custom content from a plist.
NSBundle *bundle = [NSBundle mainBundle];
NSString* plistPath = [bundle pathForResource:@"Intro" ofType:@"plist"];
[[CalStoreController sharedController] presentModalIntroFromViewController:self.window.rootViewController
withPlistPath:plistPath];
Each page of the intro is configured as dictionary.
<array>
<dict>
<key>title</key>
<string>Page1 title</string>
<key>description</key>
<string>Page1 description</string>
<key>image</key>
<string>Walkthrough-1.png</string>
<key>background_color</key>
<string>#EFEFF4</string>
<key>text_background_color</key>
<string>#E36364</string>
</dict>
</array>
The plist and images are loaded from the main bundle of your app. Consider localizing the plist file, matching you apps supported languages.