{"_id":"5ab565f212d24900747242ab","category":{"_id":"5ab565f112d249007472429b","version":"5ab565f112d2490074724298","project":"57c88b374434350e00509d7f","__v":0,"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2014-11-05T21:53:37.386Z","from_sync":false,"order":2,"slug":"reference","title":"Reference"},"project":"57c88b374434350e00509d7f","user":"55e5ba046015ce1900eadb8e","parentDoc":null,"version":{"_id":"5ab565f112d2490074724298","project":"57c88b374434350e00509d7f","__v":1,"createdAt":"2018-03-23T20:39:13.299Z","releaseDate":"2018-03-23T20:39:13.299Z","categories":["5ab565f112d2490074724299","5ab565f112d249007472429a","5ab565f112d249007472429b","5ab565f112d249007472429c"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"3.6.0","version":"3.6.0"},"githubsync":"","__v":0,"updates":[],"next":{"pages":[],"description":""},"createdAt":"2016-03-21T09:56:52.222Z","link_external":false,"link_url":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":9,"body":"The presentation of onboarding experiences is a core feature of the Primer iOS SDK.\n\n####Experience Presentation\n\nThe most common time to present an onboarding experience is right when the application launches. The best way of doing this in most of the applications is by calling the presentation method in the `-viewDidLoad` of your first screen to be presented to the user on app load. If the first view controller to be displayed is wrapped in a container controller, like a `UINavigationController` or a `UITabBarController`, then the proper place to call the presentation method is in this container controller.\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"If you present the Primer experience in the way described above, the SDK automatically mimics your launch screen while initializing the onboarding experience, thus making the user experience seamless.\"\n}\n[/block]\nTo let the SDK automatically present an onboarding experience, simply call the `+presentExperience` method, or its counterpart with a completion block. In the latter case, you get a boolean parameter called `success` which lets you know if an experience was actually presented. This automatic presentation will take the user state into account when determining whether to show an experience.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"[Primer presentExperience];\\n\\n// or\\n\\n[Primer presentExperienceWithCompletion:^(BOOL success) {\\n    // Use the parameter to determine if an experience was actually presented\\n}];\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"Primer.presentExperience()\\n\\n// or\\n\\nPrimer.presentExperience { (success: Bool) in\\n    // Use the parameter to determine if an experience was actually presented\\n}\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\nOnce an experience is presented, it handles its own dismissal in most cases. However, if there's a situation when you'd like to be sure that no experience is presented, you can achieve this by calling the `+dismissExperience` method or its counterpart with a completion block. In the latter case, you get a boolean parameter called `success`, which lets you know if there was an experience actually presented and successfully dismissed.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"[Primer dismissExperience];\\n\\n// or\\n\\n[Primer dismissExperienceWithCompletion:^(BOOL success) {\\n    // Use the parameter to determine if an experience was actually dismissed\\n}];\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"Primer.dismissExperience()\\n\\n// or\\n\\nPrimer.dismissExperience { (success: Bool) in\\n    // Use the parameter to determine if an experience was actually dismissed\\n}\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\nIf you'd like to know if there is an experience currently presenting, call `+isPresentingExperience`.\n\n####Landscape Orientation\n\nThe Primer experiences are optimized for portrait orientation, so if your application supports landscape you'll want to implement the `-application:supportedInterfaceOrientationsForWindow:` method in your app delegate and check the presentation state.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {\\n    if ([Primer isPresentingExperience]) {\\n        return UIInterfaceOrientationMaskPortrait;\\n    }\\n    return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscape;\\n}\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {\\n    guard !Primer.isPresentingExperience() else {\\n        return .portrait\\n    }\\n    return [.portrait, .landscape]\\n}\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\n####Advanced Presentation\n\nWith more complex setups and user interface structures, it's possible that the automatic solution might not be able to successfully display an onboarding experience. To solve this, the SDK provides an advanced way of presentation where you can tweak some related parameters by passing in a `PMRExperienceSettings` instance.\n\nThe most important one of these is the `presentingViewController` property. With it, you can let the SDK know which view controller to present on.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"// Tweak the presentation settings\\n\\nPMRExperienceSettings *settings = [[PMRExperienceSettings alloc] init];\\nsettings.presentingViewController = self;\\n\\n// Then use them to present the experience\\n\\n[Primer presentExperienceWithSettings:settings];\\n\\n// or\\n\\n[Primer presentExperienceWithSettings:settings andCompletion:^(BOOL success) {\\n    // Use the parameter to determine if an experience was actually presented\\n}];\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"// Tweak the presentation settings\\n        \\nlet settings = PMRExperienceSettings()\\nsettings.presentingViewController = self\\n\\n// Then use them to present the experience\\n\\nPrimer.presentExperience(with: settings)\\n\\n// or\\n\\nPrimer.presentExperience(with: settings) { (success: Bool) in\\n    // Use the parameter to determine if an experience was actually presented\\n}\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\nYou can also set the type of the experience to be presented with the `experienceType` property. The possible values are `Automatic`, `NewUser`, `Login`, and `RecoverPassword`. The automatic type behaves like the automatic presentation method, as in the SDK determines if an experience needs to be presented at all, using the user state information. The other options will show the appropriate experience, regardless of the user's logged-in status.\n\n####Custom Presentation\n\nIf you'd like to take control over the whole presentation, for example to use a custom transition, the SDK lets you do that. You have the option to load the experience (either the automatic one, or with a specific type) asynchronously, and then present it modally. This way it can dismiss itself when it's appropriate. In case there is no experience to be presented or one cannot be loaded the `viewController` parameter will simply be `nil`.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"[Primer loadExperienceWithCompletion:^(UIViewController *viewController) {\\n    // Present the view controller\\n}];\\n\\n// or\\n\\n[Primer loadExperienceType:type withCompletion:^(UIViewController *viewController) {\\n    // Present the view controller\\n}];\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"Primer.loadExperience { (viewController: UIViewController?) in\\n    // Present the view controller\\n}\\n\\n// or\\n\\nPrimer.load(type) { (viewContoller: UIViewController?) in\\n    // Present the view controller\\n}\",\n      \"language\": \"swift\"\n    }\n  ]\n}\n[/block]\n####Experience Navigation\n\nIf you'd like to go to the next screen when an experience is presented, just call `+goToNextExperienceScreen`.\nNote that this will validate the current screen before going forward.\n\n####Local Defaults\n\nIn cases when our servers cannot be accessed (such as when the user loses their internet connection), the Primer iOS SDK can use local backup files that are custom-tailored to your app to load the appropriate experiences.\n\nTo add local default, download `PMRDefault.zip` from your [Project Settings](https://goprimer.com/dashboard#/project//edit) in Dashboard. Unarchive it, then drag and drop `PMRDefault.json` and `PMRDefault.xcassets` from `iOS` into your Xcode project. Ensure the `Copy items if needed` checkbox is selected, and the right target is checked.\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"Keep your local defaults up-to-date. If you update your organic flow on the Dashboard, keep your local defaults in sync by downloading the latest version.\"\n}\n[/block]","excerpt":"","slug":"onboarding","type":"basic","title":"Onboarding"}
The presentation of onboarding experiences is a core feature of the Primer iOS SDK. ####Experience Presentation The most common time to present an onboarding experience is right when the application launches. The best way of doing this in most of the applications is by calling the presentation method in the `-viewDidLoad` of your first screen to be presented to the user on app load. If the first view controller to be displayed is wrapped in a container controller, like a `UINavigationController` or a `UITabBarController`, then the proper place to call the presentation method is in this container controller. [block:callout] { "type": "info", "body": "If you present the Primer experience in the way described above, the SDK automatically mimics your launch screen while initializing the onboarding experience, thus making the user experience seamless." } [/block] To let the SDK automatically present an onboarding experience, simply call the `+presentExperience` method, or its counterpart with a completion block. In the latter case, you get a boolean parameter called `success` which lets you know if an experience was actually presented. This automatic presentation will take the user state into account when determining whether to show an experience. [block:code] { "codes": [ { "code": "[Primer presentExperience];\n\n// or\n\n[Primer presentExperienceWithCompletion:^(BOOL success) {\n // Use the parameter to determine if an experience was actually presented\n}];", "language": "objectivec" }, { "code": "Primer.presentExperience()\n\n// or\n\nPrimer.presentExperience { (success: Bool) in\n // Use the parameter to determine if an experience was actually presented\n}", "language": "swift" } ] } [/block] Once an experience is presented, it handles its own dismissal in most cases. However, if there's a situation when you'd like to be sure that no experience is presented, you can achieve this by calling the `+dismissExperience` method or its counterpart with a completion block. In the latter case, you get a boolean parameter called `success`, which lets you know if there was an experience actually presented and successfully dismissed. [block:code] { "codes": [ { "code": "[Primer dismissExperience];\n\n// or\n\n[Primer dismissExperienceWithCompletion:^(BOOL success) {\n // Use the parameter to determine if an experience was actually dismissed\n}];", "language": "objectivec" }, { "code": "Primer.dismissExperience()\n\n// or\n\nPrimer.dismissExperience { (success: Bool) in\n // Use the parameter to determine if an experience was actually dismissed\n}", "language": "swift" } ] } [/block] If you'd like to know if there is an experience currently presenting, call `+isPresentingExperience`. ####Landscape Orientation The Primer experiences are optimized for portrait orientation, so if your application supports landscape you'll want to implement the `-application:supportedInterfaceOrientationsForWindow:` method in your app delegate and check the presentation state. [block:code] { "codes": [ { "code": "- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {\n if ([Primer isPresentingExperience]) {\n return UIInterfaceOrientationMaskPortrait;\n }\n return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscape;\n}", "language": "objectivec" }, { "code": "func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {\n guard !Primer.isPresentingExperience() else {\n return .portrait\n }\n return [.portrait, .landscape]\n}", "language": "swift" } ] } [/block] ####Advanced Presentation With more complex setups and user interface structures, it's possible that the automatic solution might not be able to successfully display an onboarding experience. To solve this, the SDK provides an advanced way of presentation where you can tweak some related parameters by passing in a `PMRExperienceSettings` instance. The most important one of these is the `presentingViewController` property. With it, you can let the SDK know which view controller to present on. [block:code] { "codes": [ { "code": "// Tweak the presentation settings\n\nPMRExperienceSettings *settings = [[PMRExperienceSettings alloc] init];\nsettings.presentingViewController = self;\n\n// Then use them to present the experience\n\n[Primer presentExperienceWithSettings:settings];\n\n// or\n\n[Primer presentExperienceWithSettings:settings andCompletion:^(BOOL success) {\n // Use the parameter to determine if an experience was actually presented\n}];", "language": "objectivec" }, { "code": "// Tweak the presentation settings\n \nlet settings = PMRExperienceSettings()\nsettings.presentingViewController = self\n\n// Then use them to present the experience\n\nPrimer.presentExperience(with: settings)\n\n// or\n\nPrimer.presentExperience(with: settings) { (success: Bool) in\n // Use the parameter to determine if an experience was actually presented\n}", "language": "swift" } ] } [/block] You can also set the type of the experience to be presented with the `experienceType` property. The possible values are `Automatic`, `NewUser`, `Login`, and `RecoverPassword`. The automatic type behaves like the automatic presentation method, as in the SDK determines if an experience needs to be presented at all, using the user state information. The other options will show the appropriate experience, regardless of the user's logged-in status. ####Custom Presentation If you'd like to take control over the whole presentation, for example to use a custom transition, the SDK lets you do that. You have the option to load the experience (either the automatic one, or with a specific type) asynchronously, and then present it modally. This way it can dismiss itself when it's appropriate. In case there is no experience to be presented or one cannot be loaded the `viewController` parameter will simply be `nil`. [block:code] { "codes": [ { "code": "[Primer loadExperienceWithCompletion:^(UIViewController *viewController) {\n // Present the view controller\n}];\n\n// or\n\n[Primer loadExperienceType:type withCompletion:^(UIViewController *viewController) {\n // Present the view controller\n}];", "language": "objectivec" }, { "code": "Primer.loadExperience { (viewController: UIViewController?) in\n // Present the view controller\n}\n\n// or\n\nPrimer.load(type) { (viewContoller: UIViewController?) in\n // Present the view controller\n}", "language": "swift" } ] } [/block] ####Experience Navigation If you'd like to go to the next screen when an experience is presented, just call `+goToNextExperienceScreen`. Note that this will validate the current screen before going forward. ####Local Defaults In cases when our servers cannot be accessed (such as when the user loses their internet connection), the Primer iOS SDK can use local backup files that are custom-tailored to your app to load the appropriate experiences. To add local default, download `PMRDefault.zip` from your [Project Settings](https://goprimer.com/dashboard#/project//edit) in Dashboard. Unarchive it, then drag and drop `PMRDefault.json` and `PMRDefault.xcassets` from `iOS` into your Xcode project. Ensure the `Copy items if needed` checkbox is selected, and the right target is checked. [block:callout] { "type": "info", "body": "Keep your local defaults up-to-date. If you update your organic flow on the Dashboard, keep your local defaults in sync by downloading the latest version." } [/block]