Onboarding - basics

Initialize the application so it can communicate with a backend system initially or upon app restart. The initialization process:

  • Retrieves the configuration from different sources. See Onboarding Configuration.
  • Authenticates using the selected authentication method to the application endpoint.
  • Sets up an SAPURLSession with all the necessary observers and authenticators.
  • Creates a store with the appropriate security to store all credentials and sensitive information gathered during the onboarding flow.

The Onboarding solution provided by the SAPFioriFlows framework includes customizable components that can be used together to meet the application’s specific requirements, and includes:

  1. Step
  2. Flow
  3. Modes of running the flow
  4. Presenting screens
  5. Running the flow: an example

1. Step

The tasks necessary to achieve the onboarded state of the application are encapsulated in different classes called steps. Each step has a well defined task. The series of steps taken together is called the flow.

SAPFioriFlows includes several steps, each with different functionality. Steps can be grouped based on their functionality:

Use the flat dictionary with given keys (OnboardingInfoKey) also referred to as info, to pass data between steps.

If a step gathers any data that might be needed in the future, for example in case of a restart, it should be persisted physically in the store by the step itself. The step that requires this data can then load it when needed.

2. Flow

There are two types of flows based on the state of the application:

  • onboarding flow – The application starts from an initial state (the first run or after a reset)
  • restoring flow – The application starts, but a persisted state already exists

A flow can contain any number of steps appropriate for the application. The steps used in a flow can be in any order that makes sense for the application, and is not controlled by the SDK. It is up to the application developer to configure and set up the flows properly. Each step has its own set of arguments which are needed to perform its task.

A general onboarding flow consist of:

  • the WelcomeScreenStep which also gathers configuration and stores it in the store
  • an authentication step which configures the SAPURLSession with the appropriate observer and authenticator, performs the authentication
  • the SAPcpmsSettingsDownloadStep which gathers the settings (for example PasswordPolicy) from the SAPcpms
  • StoreManagerStep which creates the store

A general restoring flow contains the same steps but starts with the StoreManagerStep which opens the existing SecureStore:

  • StoreManagerStep: opens the SecureStore
  • WelcomeScreenStep reloads the configuration from the store
  • an authentication step
  • the SAPcpmsSettingsDownloadStep which gather the settings, for example PasswordPolicy

3. Modes of running the flow

You can implement your own steps, or implement steps included in the SAPFioriFlows framework.

There are two ways to use the steps provided by the framework:

Usually the steps are implemented a way where the automatic methods call the manual method internally so the methods behavior is guaranteed to be the same.

See OAuth2AuthenticationStep for an example. It declares a low-level onboard method and a higher-level onboard method (which conforms to OnboardingStep protocol supporting automatic flow management):

// 'automatic' flow management method conforming to `OnboardingStep`
public func onboard(context: OnboardingContext, completionHandler: @escaping (OnboardingResult) -> Void)

// 'manual' flow management method: lists the properties the step needs
open func onboard(authenticationURL: URL, authenticationParameters: OAuth2AuthenticationParameters, sapURLSession: SAPURLSession, credentialStore: CodableStoring, presentationDelegate: FlowPresentationDelegate, completionHandler: @escaping (Error?) -> Void)

4. Presenting screens

The application can present a splash screen when the onboarding flow starts. This screen hides the application screen between the steps and also provides a consistent background for the onboarding flow. There are more splash screen use-cases. In every case, the developer must handle when to present the screen before the onboarding flow starts and dismiss the screen when the flow finishes.

  1. There is no splash screen set to PresentationDelegate The application screen is observable for a moment every time it moves between onboarding steps. If the app presents its splash screen before the onboarding flow starts, it will be visible. That screen can be replaced by the appropriate application screen at the end of the onboarding flow.

  2. The application starts with InfoViewController as a root view controller: this can be set as a splash screen to the ModalUIViewControllerPresenter (when it is used as PresentationDelegate - default) and will be visible instead of application screen when moving between steps. The information text on the screen will be updated by the steps automatically. The developer has to replace it to the application view controllers at the end of the onboarding flow:

    // instantiate the splashScreen, set it to `presentationDelegate` then start the flow
    let splashScreen = FUIInfoViewController.createSplashScreenInstanceFromStoryboard()
    <# Set it as the rootViewController #>
    // set as splash for onboarding
    presentationDelegate.setSplashScreen(splashScreen)
    
    <# run the onboarding or restoring flow #>
    
    // when the onboarding flow was successful, clear the splash screen
    (context.presentationDelegate as! ModalUIViewControllerPresenter).presentationDelegate.clearSplashScreen()
    

    You can use any custom ViewController as a splash screen if it conforms to the InfoTextSettable protocol, which can be implemented as an extension to any existing ViewController.

  3. When starting the application, the main application screen is visible, then a splash screen must be opened over the application screen using the present method of the FlowPresentationDelegate. This splash screen is visible when switching between steps. The information text on the screen will be updated by the steps automatically. You must add code to close the screen by calling dismiss on the PresentationDelegate after the onboarding flow finishes:

    // instantiate the splashScreen, call present on presentationDelegate, then in callback start the flow
    let splashScreen = FUIInfoViewController.createSplashScreenInstanceFromStoryboard()
    presentationDelegate.present(splashScreen) { _ in
      <# run the onboarding or restoring flow #>
    }
    
    // when the onboarding flow was successful, call dismiss on presentationDelegate
    context.presentationDelegate.dismiss { _ in
    }
    

Note: By default, the ModalUIViewControllerPresenter overrides the modalPresentationStyle property of the presented view controllers to .overFullScreen. This makes possible to correctly present view controllers on top of everything, including UIAlertController. However when using this presentation style, some of the underlying view controller’s methods (viewWillDisappear, viewWillAppear) won’t be called when they are hidden / showed again. You can change the default presentation style any time on ModalUIViewControllerPresenter.

5. Running the flow: an example

As described in Flow and Modes of running the flow sections, the following sample presents a general way of running an onboarding and restoring flow:

let presentationDelegate = ModalUIViewControllerPresenter()
<# Initialize, present and set the splash screen #>
presentationDelegate.setSplashScreen(<# your splash screen instance #>)
onboardOrRestore() // start the proper flow

func onboardOrRestore() {

    // declare the steps: you can use different instances as well for the onboarding/restoring flows
    let welcome = WelcomeScreenStep(providers: [<# list your configuration providers #>]) // welcome and configuration management
    let sessionConf = SAPcpmsSessionConfigurationStep() // SAPcpms compatibility
    let auth = OAuth2AuthenticationStep() // authentication
    let settings = SAPcpmsSettingsDownloadStep() // download and apply the settings
    let store = StoreManagerStep() // store management

    // initialize context
    var context = OnboardingContext(presentationDelegate: presentationDelegate)
    let onboardingFlow: [OnboardingStep] = [welcome, sessionConf, auth, settings, store]
    let restoringFlow: [OnboardingStep] = [store, welcome, sessionConf, auth, settings]

    if let savedUUIDString = UserDefaults.standard.string(forKey: "userOnboardingID"), let uuid = UUID(uuidString: savedUUIDString) {
        context.onboardingID = uuid
        OnboardingFlowController.restore(on: restoringFlow, context: context) { result
        <# handle the result, start the application logic #>
        }
    } else {
        OnboardingFlowController.onboard(on: onboardingFlow, context: context) { result
            <#handle the result and persist the onboardingID in case of success #>

            UserDefaults.standard.set(context.onboardingID.uuidString, forKey:"userOnboardingID")

            <# Save the required properties from the context to your app: SAPURLSession, Store, etc. Never save the whole context! #>

            <# start the application logic #>
        }
    }
}

Note: A production application is more complicated and must properly handle error and success cases. Use the SAP Cloud Platform SDK for iOS Assistant to generate a more detailed sample application.

  • Keys defined to access objects in a dictionary a typed way To extend the available keys define your own key the following way

     public extension OnboardingInfoKey {
         public static let myDeclaredKey = OnboardingInfoKey("myDeclaredKey")
    }
    

    Then you can use this to access information in the Dictionary

     var info = [OnboardingInfoKey: Any]()
     info[.myDeclaredKey] = MyStruct()
    
    See more

    Declaration

    Swift

    public struct OnboardingInfoKey : RawRepresentable, Equatable, Hashable, CustomStringConvertible, CustomDebugStringConvertible
  • This protocol describes a transformation from a specific value to an other object. It is used to transform a configuration to typed objects. The config source of the transformation can be a Dictionary, an Array or any simple type. Since the config can be transformed to more objects (if it is a Dictionary describing more structures) the result is a dictionary which must contain the transformed typed objects. The keys in the result dictionary must be declared first to avoid typos and provide a clear declared way of key usage

    See more

    Declaration

    Swift

    public protocol ConfigurationTransforming: class
  • Implementers must present appripriately the ViewControllers provided by the onboarding steps Different implementers can present the ViewControllers differently but must be appropriate for the ViewController design of the used steps. For example if a step uses a ViewController designed to use NavigationController the presenter must put the ViewController into a NavigationController

    See more

    Declaration

    Swift

    public protocol FlowPresentationDelegate: class
  • Implementers must use the presentationDelegate to present their ViewControllers

    See more

    Declaration

    Swift

    public protocol FlowPresentationDelegateClient: class
  • OnboardingStep Represents a step in the onboarding/restoring flow.

    See more

    Declaration

    Swift

    public protocol OnboardingStep : class
  • This FlowPresentationDelegate implementation handles the screen presentation in such a way, that every present call results in a modal presentation on the top-most view controller.

    Important: This implementation requires that every present call have their own dismiss call pair. Self dismissing view controllers such as UIAlertControllers are not supported.

    See more

    Declaration

    Swift

    open class ModalUIViewControllerPresenter: FlowPresentationDelegate
  • Class for Welcome Screen onboarding step handling UI elements of the Welcome Screen are localizable through the step’s welcomeScreenCustomizationHandler which will be called during the WelcomeStep onboarding process to configure the screen.

    ## Customization

    
     // The customized WelcomeStep can be created like the following code snippet
     func configuredWelcomeScreenStep() -> WelcomeScreenStep {
        let discoveryConfigurationTransformer = DiscoveryServiceConfigurationTransformer(applicationID: "sample.application.id", authenticationPath: "sample.application.id")
        let welcomeScreen = WelcomeScreenStep(transformer: discoveryConfigurationTransformer, providers: [FileConfigurationProvider()])
    
       let welcomeScreenBundle = Bundle(for: WelcomeScreenStep.self)
       let localizedHeadlineLabelText = NSLocalizedString("WelcomeScreenHeadlineLabelKey", tableName: "ExampleTableName", bundle: welcomeScreenBundle, value: "Example Headline Text", comment: "")
       let localizedDetailLabelText = NSLocalizedString("WelcomeScreenDetailLabelKey", tableName: "ExampleTableName", bundle: welcomeScreenBundle, value: "Example Headline Text", comment: "")
       let localizedPrimaryActionButtonText = NSLocalizedString("WelcomeScreenPrimaryActionButtonTextKey", tableName: "ExampleTableName", bundle: welcomeScreenBundle, value: "Example Headline Text", comment: "")
       let localizedFootnoteActionButtonTitleText = NSLocalizedString("WelcomeScreenFootnoteActionButtonTextKey", tableName: "ExampleTableName", bundle: welcomeScreenBundle, value: "Example Headline Text", comment: "")
       let localizedFootnoteLabelText = NSLocalizedString("WelcomeScreenFootnoteLabelTextKey", tableName: "ExampleTableName", bundle: welcomeScreenBundle, value: "Example Headline Text", comment: "")
    
       welcomeScreen.welcomeScreenCustomizationHandler = { welcomeScreen in
           welcomeScreen.headlineLabel.text = localizedHeadlineLabelText
           welcomeScreen.detailLabel.text = localizedDetailLabelText
           welcomeScreen.primaryActionButton.titleLabel?.text = localizedPrimaryActionButtonText
           welcomeScreen.footnoteActionButton.setTitle(localizedFootnoteActionButtonTitleText, for: .normal)
           welcomeScreen.footnoteLabel.text = localizedFootnoteLabelText
       }
    
       return welcomeScreen
     }
    
    
    See more

    Declaration

    Swift

    open class WelcomeScreenStep: OnboardingStep, FUIWelcomeControllerDelegate, FUIOnboardingScanViewControllerDelegate
  • Instantiates an OnboardingStep capable of registering the SAPcpmsObserver observer in the onboard / restore flow.

    If you wish to use this funcionality in manual mode, you can use this one-liner instead of this class:

    let sapURLSession = <#SAPURLSession#>
    sapURLSession.register(<#SAPcpmsObserver#>)
    
    See more

    Declaration

    Swift

    open class SAPcpmsSessionConfigurationStep: SimpleTaskStep
  • Onboarding step implementation of Basic Authentication Used in the onboarding/restoring flow, this step is responsible to configure the app’s URLSession to be able to communicate with basic authentication protected resources. Creates and registers the BasicAuthenticationObserver to the SAPURLSession, then sends a validation request which will trigger an authentication flow.

    Customization

    During the onboarding flow, if there is a splash screen which shows a text, that text can be changed/localized.

    // The customized WelcomeStep can be created like the following code snippet
    func customBasicAuthStep() -> OnboardingStep {
       let basicAuthenticationBundle = Bundle(for: BasicAuthenticationStep.self)
    
       let localizedInfoScreenText = NSLocalizedString("BasicInfoScreenText", tableName: "Example Table name", bundle: basicAuthenticationBundle, value: "Validating Basic credentials", comment: "")
       let localizedCancelButtonText = NSLocalizedString("CancelButtonText", tableName: "Example Table name", bundle: basicAuthenticationBundle, value: "Cancel", comment: "")
       let localizedInformationLabelText = NSLocalizedString("BasicInformationLabelTextKey", tableName: "Example Table name", bundle: basicAuthenticationBundle, value: "Authentication", comment: "")
       let localizedHeadLineLabelText = NSLocalizedString("BasicHeadLineLabelTextKey", tableName: "Example Table name", bundle: basicAuthenticationBundle, value: "Please enter your credentials", comment: "")
       let localizedSignInButtonText = NSLocalizedString("BasicSignInButtonText", tableName: "Example Table name", bundle: basicAuthenticationBundle, value: "Sign In", comment: "")
       let localizedUsernamePlaceholderText = NSLocalizedString("BasicUsernamePlaceholderTextKey", tableName: "Example Table name", bundle: basicAuthenticationBundle, value: "Username", comment: "")
       let localizedPasswordPlaceholderText = NSLocalizedString("BasicPasswordPlaceholderTextKey", tableName: "Example Table name", bundle: basicAuthenticationBundle, value: "Password", comment: "")
    
       let presenter = FioriBasicCredentialsViewControllerPresenter()
       presenter.basicViewControllerConfigurationHandler = { basicView in
            basicView.headlineLabel.text = localizedHeadLineLabelText
            basicView.informationLabel.text = localizedInformationLabelText
            basicView.signInButton.titleLabel?.text = localizedSignInButtonText
            basicView.usernameTextField.emailTextField.placeholder = localizedUsernamePlaceholderText
            basicView.passwordTextField.emailTextField.placeholder = localizedPasswordPlaceholderText
            basicView.navigationItem.leftBarButtonItem?.title = localizedCancelButtonText
       }
       let step = BasicAuthenticationStep(presenter: presenter)
       step.infoScreenText = localizedInfoScreenText
    
       return step
    }
    
    See more

    Declaration

    Swift

    open class BasicAuthenticationStep: OnboardingStep
  • OAuth 2.0 onboarding step.

    Used in the onboarding / restoring flow, this step is responsible to configure the app’s URLSession to be able to communicate with OAuth 2.0 protected resources. Creates and registers the OAuth2Observer to the SAPURLSession, then sends a validation request which will trigger an authentication flow.

    Customization

    During the onboarding flow, if there is a splash screen which shows a text, that text can be changed/localized. The presented webView will also have localizable components, but the localization of downloaded data depends on the server and is not customizable from the created client application.

    func customOauth2AuthStep() -> OnboardingStep {
       let oauth2Bundle = Bundle(for: OAuth2AuthenticationStep.self)
    
       let localizedInfoScreenText = NSLocalizedString("Oauth2InfoScreenText", tableName: "Example Table name", bundle: oauth2Bundle, value: "Validating OAuth2 credentials", comment: "")
       let localizedCancelButtonText = NSLocalizedString("CancelButtonText", tableName: "Example Table name", bundle: oauth2Bundle, value: "Cancel", comment: "")
    
       let presenter = FioriUIWebViewPresenter()
       presenter.webViewControllerConfigurationHandler = { webView in
           webView.cancelButton?.title = localizedCancelButtonText
    
           return webView
       }
    
       let step = OAuth2AuthenticationStep(presenter: presenter)
       step.infoScreenText = localizedInfoScreenText
    
       return step
    }
    
    See more

    Declaration

    Swift

    open class OAuth2AuthenticationStep: OnboardingStep
  • SAML 2.0 onboarding step.

    Used in the onboarding / restoring flow, this step is responsible to configure the app’s URLSession to be able to communicate with SAML 2.0 protected resources. Creates and registers the SAMLObserver to the SAPURLSession, then sends a validation request which will trigger an authentication flow.

    Customization

    During the onboarding flow, if there is a splash screen which shows a text, that text can be changed/localized. The presented webView will also have localizable components, but the localization of downloaded data depends on the server and is not customizable from the created client application.

    func customSAMLAuthStep() -> OnboardingStep {
       let samlBundle = Bundle(for: SAMLAuthenticationStep.self)
    
       let localizedInfoScreenText = NSLocalizedString("SAMLInfoScreenText", tableName: "Example Table name", bundle: samlBundle, value: "Validating SAML credentials", comment: "")
       let localizedCancelButtonText = NSLocalizedString("CancelButtonText", tableName: "Example Table name", bundle: samlBundle, value: "Cancel", comment: "")
    
       let presenter = FioriUIWebViewPresenter()
       presenter.webViewControllerConfigurationHandler = { webView in
           webView.cancelButton?.title = localizedCancelButtonText
    
           return webView
       }
    
       let step = SAMLAuthenticationStep(presenter: presenter)
       step.infoScreenText = localizedInfoScreenText
    
       return step
    }
    
    See more

    Declaration

    Swift

    open class SAMLAuthenticationStep: OnboardingStep
  • Onboarding step implementation of SLS certificate authentication Used in the onboarding/restoring flow, this step is responsible to configure the app’s URLSession to be able to communicate with SLS authentication protected resources. Creates and registers the UserIdentityObserver to the SAPURLSession, then sends a validation request which will trigger an authentication flow.

    Customization

    During the onboarding flow, if there is a splash screen which shows a text, that text can be changed/localized.

    // The customized WelcomeStep can be created like the following code snippet
    func customSLSAuthStep() -> OnboardingStep {
       let slsAuthenticationBundle = Bundle(for: SLSAuthenticationStep.self)
    
       let localizedInfoScreenText = NSLocalizedString("SLSInfoScreenText", tableName: "Example Table name", bundle: slsAuthenticationBundle, value: "Validating credentials", comment: "")
       let localizedCancelButtonText = NSLocalizedString("CancelButtonText", tableName: "Example Table name", bundle: slsAuthenticationBundle, value: "Cancel", comment: "")
       let localizedInformationLabelText = NSLocalizedString("SLSInformationLabelTextKey", tableName: "Example Table name", bundle: slsAuthenticationBundle, value: "Please enter your credentials", comment: "")
       let localizedSignInButtonText = NSLocalizedString("SLSSignInButtonText", tableName: "Example Table name", bundle: slsAuthenticationBundle, value: "Sign In", comment: "")
    
       let presenter = SLSLoginInputPresenter()
       presenter.loginViewControllerConfigurationHandler = { viewController in
            viewController.informationLabel.text = localizedInformationLabelText
            viewController.navigationItem.leftBarButtonItem?.title = localizedCancelButtonText
            viewController.navigationItem.rightBarButtonItem?.title = localizedSignInButtonText
       }
       let step = SLSAuthenticationStep(slsLoginInputPresenter: presenter)
       step.infoScreenText = localizedInfoScreenText
    
       return step
    }
    
    See more

    Declaration

    Swift

    open class SLSAuthenticationStep: OnboardingStep
  • OTP onboarding step.

    Used in the onboarding / restoring flow, this step is responsible to configure the app’s URLSession to be able to communicate with OTP protected resources. Creates and registers the OTPObserver. This step should be set before the authentication step (can be used with Basic, OAuth 2.0 and SAML 2.0 authentications).

    Customization

    During the onboarding flow, if there is a splash screen which shows a text, that text can be changed/localized. The presented webView will also have localizable components, but the localization of downloaded data depends on the server and is not customizable from the created client application.

    func customSAMLAuthStep() -> OnboardingStep {
       let samlBundle = Bundle(for: SAMLAuthenticationStep.self)
    
       let localizedInfoScreenText = NSLocalizedString("SAMLInfoScreenText", tableName: "Example Table name", bundle: samlBundle, value: "Validating SAML credentials", comment: "")
       let localizedCancelButtonText = NSLocalizedString("CancelButtonText", tableName: "Example Table name", bundle: samlBundle, value: "Cancel", comment: "")
    
       let presenter = FioriUIWebViewPresenter()
       presenter.webViewControllerConfigurationHandler = { webView in
           webView.cancelButton?.title = localizedCancelButtonText
    
           return webView
       }
    
       let step = SAMLAuthenticationStep(presenter: presenter)
       step.infoScreenText = localizedInfoScreenText
    
       return step
    }
    
    See more

    Declaration

    Swift

    open class OTPSessionConfigurationStep: OnboardingStep
  • Class for SAPcpmsSettings download onboarding step handling

    Customization

    During the onboarding flow, if there is a splash screen which shows a text, that text can be changed/localized.

    
    // The localized SAPcpmsSettingsDownloadStep can be created like the following code snippet
    func customSettingsDownloadStep() -> OnboardingStep {
       let step = SAPcpmsSettingsDownloadStep()
    
       let sapcpmsSettingsDownloadBundle = Bundle(for: SAPcpmsSettingsDownloadStep.self)
       step.infoScreenText = NSLocalizedString("SAPcpmsSettingsDownloadInfoScreenTextKey", tableName: "ExampleTableName", bundle: sapcpmsSettingsDownloadBundle, value: "Example Info Screen Text", comment: "")
    
       return step
    }
    
    
    See more

    Declaration

    Swift

    open class SAPcpmsSettingsDownloadStep: OnboardingStep
  • Manages the End User License Agreement (EULA) handling. The EULA version will be stored in the credentialStore of the OnboardingContext which is used to decide if a new EULA screen should be presented on the next run. If the user has not confirmed EULA, or a new EULA content is present, a screen will be displayed to request user confirmation.

    Usage

    let title = "SAP - EULA"
    let text = """
    This is a legally binding agreement (Agreement) between Company and SAP SE which provides the terms of your use of the SAP mobile application (Software). By clicking "Accept" or by installing and/or using the Software, you on behalf of the Company are agreeing to all of the terms and conditions stated in this Agreement. If you do not agree to these terms, do not click "Agree", and do not use the Software. You represent and warrant that you have the authority to bind the Company to the terms of this Agreement.
    """
    let attributes = [NSAttributedStringKey.font: UIFont(name: "Georgia", size: 17.0)!]
    let content = NSAttributedString(string: content, attributes: attributes)
    let eulaContent = EULAContent(title: title, content: content, version: "1.0")
    let eulaStep = EULAStep(eulaContent: eulaContent)
    
    See more

    Declaration

    Swift

    open class EULAStep: OnboardingStep, FUIEULADelegate
  • Manages the persistent store in the onboarding flow Creates and opens a SecureKeyValueStore instance in the folder specified by SecureStoreFolderPath parameter or in applicationSupportDirectory when not specified including the OnboardingID in the file name. The StoreManagerStep uses multiple screens from SAPFiori, for example TouchID and Passcode screens. The texts on these screens are also customizable. The localizable UI components are grouped in FUIPasscodeController. The following example code snippet describes how to change/localize elements of StoreManagerStep

    Customization

    func customStoreManagerStep() -> OnboardingStep {
    
       let storeManagerStepBundle = Bundle(for: StoreManagerStep.self)
       let localizedChoosePasscodeTitleString = NSLocalizedString("StoreManagerChoosePasscodeTitleKey", tableName: "ExampleTableName", bundle: storeManagerStepBundle, value: "Example choose passcode text", comment: "")
       let localizedConfirmPasscodeString = NSLocalizedString("StoreManagerConfirmPasscodeKey", tableName: "ExampleTableName", bundle: storeManagerStepBundle, value: "Example confirm passcode text", comment: "")
       let localizedLearnMoreTouchIDLinkString = NSLocalizedString("StoreManagerLearnMoreTouchIDLinkKey", tableName: "ExampleTableName", bundle: storeManagerStepBundle, value: "Example learn more about touch id text", comment: "")
       let localizedSetPasscodeMessageFormat = NSLocalizedString("StoreManagerSetPasscodeMessageFormatKey", tableName: "ExampleTableName", bundle: storeManagerStepBundle, value: "Example set passcode message", comment: "")
       // ... localizations for other components
    
       FUIPasscodeController.choosePasscodeTitleString = localizedChoosePasscodeTitleString
       FUIPasscodeController.confirmPasscodeString = localizedConfirmPasscodeString
       FUIPasscodeController.learnMoreTouchIDLinkString = localizedLearnMoreTouchIDLinkString
       FUIPasscodeController.setPasscodeMessageFormat = localizedSetPasscodeMessageFormat
       // ... setting localization of other components ...
       return StoreManagerStep()
    
    } ```
    
    See more

    Declaration

    Swift

    open class StoreManagerStep: OnboardingStep, FUIPasscodeControllerDelegate, FUIPasscodeValidationDelegate