-
Notifications
You must be signed in to change notification settings - Fork 38
White Label Onboarding
OBAKit contains prebuilt views for "onboarding" a user, located in the OBAKit/Onboarding
folder. These are SwiftUI views that can be displayed standalone or as part of a navigation stack.
sequenceDiagram
participant AppDelegate as -[AppDelegate applicationReloadRootInterface:]
AppDelegate-->+OnboardingNavigationController: needsToOnboard?
AppDelegate->>+OnboardingNavigationController: Present OnboardingNavigationController
OnboardingNavigationController->>+OnboardingView: Push One-Time Location Permission Page
OnboardingView->>-OnboardingNavigationController: dismiss()
OnboardingNavigationController->>+OnboardingView: Push Region Picker Page
OnboardingView->>-OnboardingNavigationController: dismiss()
OnboardingNavigationController->>-AppDelegate: Finish by calling OnboardingNavigationController.completion()
AppDelegate-->+AppDelegate: Present OBAClassicApplicationRootController
Take a look in OBAKit/Onboarding
to see if there is already an onboarding view you want. Otherwise, read below on how to create a custom onboarding view.
An onboarding view is a SwiftUI view that conforms to protocol OBAKit.OnboardingView
.
To implement OnboardingView
, use the below code snippet as guidance:
struct MyCustomOnboardingView: View, OnboardingView {
@Environment(\.dismiss) var dismissAction
var dismissBlock: VoidBlock?
var body: some View {
Button("Next Step") {
dismiss() // This calls `OnboardingView.dismiss()`, which has a default implementation.
}
}
}
import SwiftUI
import OBAKit
@objc public class OnboardingNavigationController: UINavigationController {
@objc public static var needsToOnboard: Bool {
// A "cheap" method to check whether we should show the user the Onboarding screen
// before actually initializing this class.
return UserDefaults.standard.bool(for: "UserHasOnboarded", default: false)
}
var completionHandler: VoidBlock
// When onboarding is finished, OnboardingNavigationController calls completionHandler.
@objc public init(completionHandler: @escaping VoidBlock) {
self.completionHandler = completionHandler
super.init(nibName: nil, bundle: nil)
}
override public func viewDidLoad() {
super.viewDidLoad()
let view = MyCustomOnboardingView(dismissBlock: self.completionHandler)
self.setViewControllers([UIHostingController(rootView: view)])
}
}
In your app's AppDelegate, implement -[AppDelegate applicationReloadRootInterface:]
. In the method, check if the user needsToOnboard
to show either the Application Controller or the Onboarding Controller.
- (void)applicationReloadRootInterface:(OBAApplication*)application {
void(^showRootController)(void) = ^{
self.rootController = [[OBAClassicApplicationRootController alloc] initWithApplication:application];
self.window.rootViewController = self.rootController;
};
if ([OnboardingNavigationController needsToOnboard]) {
self.window.rootViewController = [[OnboardingNavigationController alloc] initWithCompletion:^{
showRootController();
[UIView transitionWithView:self.window duration:0.5 options:UIViewAnimationOptionTransitionFlipFromLeft animations:nil completion:nil];
}];
} else {
showRootController();
}
}
Take a look at Apps/OneBusAway/AppDelegate.m
for an Onboarding example that implements multiple pages.