If you don’t like a default personalization view controller or you need to make significant changes beyond basic theming and customization, you can override the entire View Controller for a VOPersonalizationOption and use your own.

If you are using the VOVoucherCreationViewController and the VOVoucherCreationFlowCoordinator to launch the create flow, overriding is done by following these steps:

  1. Create your custom View Controller and make it conform to the VOPersonalizationOptionViewControllerProtocol. This is a simple protocol that has an initalizer and a VOPersonalizationOptionViewControllerDelegate.
  2. Call the VOPersonalizationOptionViewControllerDelegate methods for cancel and finish when you dismiss your custom view controller.
  3. Implement the
- (void)personalizationOptionViewController:(UIViewController <VOPersonalizationOptionViewControllerProtocol> *)viewController
                      personalizationOption:(VOPersonalizationOption *)personalizationOption
                 selectedPersonalizedObject:(id)selectedPersonalizedObject;
func personalizationOptionViewController(_ viewController: (UIViewController & VOPersonalizationOptionViewControllerProtocol)?, personalizationOption: VOPersonalizationOption?, selectedPersonalizedObject: Any?)

method of the VOVoucherCreationFlowDelegate and return your custom view controller for the proper VOPersonalizationOption.

  1. Optionally implement
- (VOCreationItemView *)creationItemViewForPersonalizationOption:(VOPersonalizationOption *)personalizationOption personalizedObject:(id)personalizedObject;
func creationItemView(for personalizationOption: VOPersonalizationOption?, personalizedObject: Any?) -> VOCreationItemView?

of the VOVoucherCreationFlowDelegate if you want a custom view dropped into the VOEnvelopeView.

Example

This is a basic example of overriding the VOTitlePersonalizationOption.

Step 1 and 2

Create a Custom View Controller, implement VOPersonalizationOptionViewControllerProtocol and call VOPersonalizationOptionViewControllerDelegate methods.

#import "SurpriiseTitleViewController.h"

@interface SurpriiseTitleViewController ()

@property (nonatomic, weak) IBOutlet UITextView *addTitleTextView;
@property (nonatomic, weak) IBOutlet UIButton *cancelButton;
@property (nonatomic, weak) IBOutlet UIButton *doneButton;

@property (nonatomic) VOTitlePersonalizationOption *titlePersonalizationOption;

@end

@implementation SurpriiseTitleViewController

#pragma mark - VOPersonalizationOptionViewControllerProtocol

@synthesize delegate;

+ (instancetype)viewControllerWithPersonalizationOption:(VOPersonalizationOption *)personalizationOption
                                          createManager:(VOVoucherCreationManager *)createManager
                                     createFlowDelegate:(id<VOVoucherCreationFlowDelegate>)createFlowDelegate {
    SurpriiseTitleViewController *surpriiseTitleViewController = [[SurpriiseTitleViewController alloc] initWithNibName:NSStringFromClass([self class]) bundle:[NSBundle bundleForClass:[self class]]];
    surpriiseTitleViewController.titlePersonalizationOption = (VOTitlePersonalizationOption *)personalizationOption;
    return surpriiseTitleViewController;
}

#pragma mark - IBActions

- (IBAction)onDone:(id)sender {
    [self dismissViewControllerAnimated:YES completion:^{
        if ([self.delegate respondsToSelector:@selector(personalizationOptionViewController:personalizationOption:selectedPersonalizedObject:)]) {
            [self.delegate personalizationOptionViewController:self personalizationOption:self.titlePersonalizationOption selectedPersonalizedObject:@{@"title": self.addTitleTextView.text}];
        }
    }];
}

- (IBAction)onCancel:(id)sender {
    [self dismissViewControllerAnimated:YES completion:^{
        if ([self.delegate respondsToSelector:@selector(personalizationOptionViewControllerCancelled:)]) {
            [self.delegate personalizationOptionViewControllerCancelled:self];
        }
    }];
}

@end 
// SurpriiseTitleViewController.swift

class SurpriiseTitleViewController: UIViewController, VOPersonalizationOptionViewControllerProtocol {
    
    @IBOutlet weak var addTitleTextView: UITextView!
    @IBOutlet weak var cancelButton: UIButton!
    @IBOutlet weak var doneButton: UIButton!
    
    var delegate: VOPersonalizationOptionViewControllerDelegate!
    var titlePersonalizationOption:VOTitlePersonalizationOption?
    
    static func viewController(with personalizationOption: VOPersonalizationOption!, createManager: VOVoucherCreationManager!, createFlowDelegate: VOVoucherCreationFlowDelegate!) -> Self? {
        let viewController:SurpriiseTitleViewController = SurpriiseTitleViewController(nibName: NSStringFromClass(self), bundle: Bundle.main);
        viewController.titlePersonalizationOption = personalizationOption as? VOTitlePersonalizationOption
        
        return unsafeDowncast(viewController, to: self);
    }
    
    @IBAction func onDone(sender: UIButton) {
        self.dismiss(animated: true) {
            if (self.delegate.responds(to:#selector(PersonalizationOptionViewControllerDelegate.personalizationOptionViewControllerCancelled(_:)))) {
                self.delegate.personalizationOptionViewControllerCancelled(self)
            }
        }
    }
    
    @IBAction func onCancel(sender: UIButton) {
        self.dismiss(animated: true) {
            if (self.delegate.responds(to: #selector(PersonalizationOptionViewControllerDelegate.personalizationOptionViewController(_:personalizationOption:selectedPersonalizedObject:)))) {
                self.delegate.personalizationOptionViewController(self, personalizationOption: self.titlePersonalizationOption, selectedPersonalizedObject: ["title": self.addTitleTextView.text])
            }
        }
    }
}

Step 3 and 4

Implement VOVoucherCreationFlowDelegate methods.

- (nullable UIViewController<VOPersonalizationOptionViewControllerProtocol> *)personalizationViewControllerForPersonalizationOption:(VOPersonalizationOption *)personalizationOption {
    if (personalizationOption.type == VOPersonalizationTypeTitle) {
        return [SurpriiseTitleViewController viewControllerWithPersonalizationOption:personalizationOption createManager:nil createFlowDelegate:nil];
    } else {
        return nil;
    }
}

- (VOCreationItemView *)creationItemViewForPersonalizationOption:(VOPersonalizationOption *)personalizationOption personalizedObject:(id)personalizedObject {
    if (personalizationOption.type == VOPersonalizationTypeTitle) {
        // turn a label into a `CreationItemView`
        UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
        label.text = personalizedObject[@"title"];
        label.backgroundColor = [UIColor redColor];
        label.textColor = [UIColor whiteColor];
        [label sizeToFit];
        VOCreationItemView *itemView = [VOCreationItemView creationItemViewWithType:VOPersonalizationTypeTitle
                                                                            subType:0
                                                                             itemId:0
                                                                         isEditable:YES
                                                                        isRemovable:YES
                                                                viewToRenderAsImage:label
                                                                        borderWidth:0
                                                                        borderColor:nil];
        CGRect frame = itemView.frame;
        frame.size = label.frame.size;
        itemView.frame = frame;
        return itemView;
    } else {
        return nil;
    }
}
func personalizationViewController(for personalizationOption: VOPersonalizationOption?) -> (UIViewController & VOPersonalizationOptionViewControllerProtocol)? {
    if (personalizationOption.type == VOPersonalizationTypeTitle) {
        return SurpriiseTitleViewController(personalizationOption: personalizationOption, createManager: nil, createFlowDelegate: nil)!
    } else {
        return nil
    }
}

func creationItemView(for personalizationOption: VOPersonalizationOption?, personalizedObject: Any?) -> VOCreationItemView? {
    if personalizationOption.type == VOPersonalizationTypeTitle {
        // turn a label into a `CreationItemView`
        let label = UILabel(frame: CGRect.zero)
        label.text = (personalizedObject as! Dictionary)["title"]
        label.backgroundColor = UIColor.red
        label.textColor = UIColor.white
        label.sizeToFit()
        let itemView = VOCreationItemView.init(type: VOPersonalizationTypeTitle, subType: 0, itemId: 0, isEditable: true, isRemovable: true, viewToRenderAsImage:label, borderWidth: 0, borderColor: nil)
        itemView?.frame.size = label.frame.size
        return itemView
    } else {
        return nil
    }
}