Overriding the Creation Screen
Scenario - Use our default view controllers, launch them from custom UI
Step 1
In the VOVoucherCreationFlowDelegate
, implement:
- (UIViewController<VOVoucherCreationViewControllerProtocol> *)customCreationViewController;
func customCreationViewController() -> (UIViewController & VOVoucherCreationViewControllerProtocol) {}
to instantiate your custom creation view controller.
(Note: When you launch the creation flow, the VOVoucherCreationFlowCoordinator
, will assign itself a creation view controller. It will use the default creation view controller if you do not implement the above method.)
Step 2
Your creation view controller should adopt the VOVoucherCreationViewControllerProtocol
.
The following is a sample implementation of an initializer:
+ (instancetype)yourCreationViewControllerWithVoucherCreationManager:(VOVoucherCreationManager *)createManager
creationFlowCoordinator:(VOVoucherCreationFlowCoordinator *)creationFlowCoordinator
createFlowDelegate:(id<VOVoucherCreationFlowDelegate>)createFlowDelegate
vouchrTheme:(VOTheme *)vouchrTheme
personalizationOptions:(NSArray<VOPersonalizationOption *> *)personalizationOptions {
NSBundle *bundle = [NSBundle bundleForClass:[YourCreationViewController class]];
YourCreationViewController *viewController = [[YourCreationViewController alloc] initWithNibName:NSStringFromClass([YourCreationViewController class]) bundle:bundle];
viewController.createManager = createManager;
viewController.creationFlowCoordinator = creationFlowCoordinator;
viewController.createFlowDelegate = createFlowDelegate;
viewController.vouchrTheme = vouchrTheme;
viewController.personalizationOptions = personalizationOptions;
viewController.mutableVoucher = createManager.mutableVoucher;
viewController.creationItems = [NSMutableArray new];
return viewController;
}
class func voucherCreationViewController(with createManager: VOVoucherCreationManager, creationFlowCoordinator: VOVoucherCreationFlowCoordinator, createFlowDelegate: VOVoucherCreationFlowDelegate, vouchrTheme: VOTheme, personalizationOptions: [VOPersonalizationOption]) -> Self {
let bundle = Bundle(for: YourViewController.self)
let viewController = YourViewController(nibName: NSStringFromClass(YourViewController.self), bundle: bundle)
viewController.createManager = createManager
viewController.creationFlowCoordinator = creationFlowCoordinator
viewController.createFlowDelegate = createFlowDelegate
viewController.vouchrTheme = vouchrTheme
viewController.personalizationOptions = personalizationOptions
viewController.mutableVoucher = createManager.mutableVoucher
viewController.creationItems = [VOCreationItemView]()
return viewController
}
(Note: assign the mutableVoucher property of the VOVoucherCreationManager
to the mutableVoucher property of your creation view controller. You may also want to initialize your array of creationItems here, or you can lazily load them, etc. )
Step 3
Your creation view controller is responsible for setting up the UI to select and launch the various personalization options it was initialized with in step 2.
The following is a sample implementation using a collection view to present the personalization options:
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return self.personalizationOptions.count;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
[collectionView deselectItemAtIndexPath:indexPath animated:YES];
VOPersonalizationOption *personalizationOption = self.personalizationOptions[indexPath.item];
[self.creationFlowCoordinator launchPersonalizationViewControllerForPersonalizationOption:personalizationOption];
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return personalizationOptions.count
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
collectionView.deselectItem(at: indexPath, animated: true)
let personalizationOption: VOPersonalizationOption? = personalizationOptions[indexPath.item]
creationFlowCoordinator.launchPersonalizationViewController(forPersonalizationOption: personalizationOption)
}
(Note: self.delegate refers to the VOVoucherCreationFlowCoordinator
instance that assigned itself as the VOVoucherCreationFlowDelegate
of your voucher creation view controller. It assigned itself when it launched the creation view controller.)
(Note 2: launchPersonalizationViewControllerForPersonalizationOption:
returns a view controller if launchPersonalizationViewControllerForPersonalizationOption:
was implemented by the VOVoucherCreationFlowDelegate
in step 1. Otherwise it launches the default view controller associated with the personalization option.)
Step 4
The creation flow coordinator will take care of updating the voucher when users add a personalization. When a personalization is added, you can receive its VOCreationItemView
to display or animate for users. To update the screen after a new personalization is added, implement:
- (void)didUpdateVoucherWithCreationItemView:(VOCreationItemView *)creationItemView withCompletion:(void (^)(void))completion;
func didUpdateVoucher(with creationItemView: VOCreationItemView?, withCompletion completion: @escaping () -> Void) {}
Optional - Send, Edit, Preview, Prepopulate
You will generally want a reference the VOVoucherCreationFlowCoordinator
initialized during setup. You will call methods on the VOVoucherCreationFlowCoordinator
instance to send, edit, and preview the reveal animation of the voucher.
Sending
To send a voucher using our default send voucher view controller, your button or other event handling UI element should implement the following when a user taps on it:
- (void)sendButtonPressed:(UIButton *)sender {
[self.creationFlowCoordinator launchSendVoucherScreenFromCreationViewControllerWithCreationItems:self.creationItems
backgroundColor:backgroundColor];
}
func sendButtonPressed(_ sender: UIButton?) {
creationFlowCoordinator.launchSendVoucherScreenFromCreationViewController(withCreationItems: creationItems, backgroundColor: backgroundColor)
}
Editing
To start the edit voucher flow, your Edit button should implement the following:
- (IBAction)editButtonPressed:(UIButton *)sender {
[self.creationFlowCoordinator launchEditScreenFromCreationViewControllerWithCreationItems:self.creationItems];
}
@IBAction func editButtonPressed(_ sender: UIButton) {
creationFlowCoordinator.launchEditScreenFromCreationViewController(withCreationItems: creationItems)
}
(NOTE: editing currently still goes through the surpriise flow: Preview Screen -> Creation Screen -> Personalization View Controller; TODO: launch personalization screens directly?)
delegate callbacks
The default editing flow allows for rearranging, and deleting creation items. You can receive updated creation items through the following two methods. Implement them to, for example, update your creation view controller’s creation items array after editing:
- (void)didEditVoucherWithRearrangedCreationItems:(NSMutableArray<CreationItemImageView *> *)creationItems;
- (void)didEditVoucherWithDeletedCreationItems:(NSMutableArray<CreationItemImageView *> *)creationItems;
func didEditVoucher(withRearrangedCreationItems creationItems: [CreationItemImageView]) {}
func didEditVoucher(withDeletedCreationItems creationItems: [CreationItemImageView]) {}
Preview Reveal Animation
To preview the reveal animation from your creation view controller, implement a variation of the following:
- (IBAction)previewButtonPressed:(UIButton *)sender {
[self.creationFlowCoordinator launchRevealScreenFromCreationViewControllerWithVoucher:self.mutableVoucher];
}
@IBAction func previewButtonPressed(_ sender: UIButton) {
creationFlowCoordinator.launchRevealScreenFromCreationViewController(withVoucher: mutableVoucher)
}
Prepopulate
You can prepopulate a voucher with contents from an ‘Occasion’ loaded from the VODiscoverScreenV1ViewController
.
In your setup class, launch the flow through the discover screen by calling the following method through your VOVoucherCreationFlowCoordinator
:
[self.voucherCreationFlowCoordinator launchDiscoverScreenVersion:DiscoverScreenVersion
onViewController:self
personalizationOptions:[self personalizations]
discoverBuilder:^(VODiscoverScreenBuilder * _Nonnull builder) {
// set builder properties here
}];
voucherCreationFlowCoordinator.launch(DiscoverScreenVersion, on: self, personalizationOptions: personalizations(), discoverBuilder: { builder in
// set builder properties here
})
In the flow, a user selects an VOOccasion
, and proceeds to the VOPreviewVoucherContentsViewController
. Next, the user taps the “Use It” button to initiate prepopulation. One by one, each personalization is added to the voucher, and each time a callback is made to the following method:
- (void)didUpdateVoucherWithCreationItemView:(nullable VOCreationItemView *)creationItemView withCompletion:(nullable void (^)(void))completion {
[self.creationItems addObject:creationItem];
[self.tableView reloadData];
}
func didUpdateVoucher(with creationItemView: VOCreationItemView?, withCompletion completion: (() -> Void)? = nil) {
creationItems.append(creationItem)
tableView.reloadData()
}
This example implementation adds a VOCreationItemView
to the view controller’s creationItems array, and reloads the tableView. Your implementation will be specific to your custom creation view controller.