Every flow presentation resolves to a FlowResult describing how the flow ended and what state it produced.
Every way you present a flow ends with a FlowResult. It tells you how the flow finished, which screens the user saw, what variables the flow captured, and which experiment variant (if any) the user got. Read it to branch your app logic, persist a captured choice, or attribute a conversion.You get a FlowResult from:
public struct FlowResult: Sendable { public let outcome: FlowOutcome public let finalVariables: [String: VariableValue] public let screensVisited: [String] public let durationMs: Int public let experimentAssignments: [String: String] public let error: FlowPilotError?}public enum FlowOutcome: String, Sendable { case completed case dismissed case error}
Field
Type
What it tells you
outcome
FlowOutcome
How the flow ended: .completed, .dismissed, or .error. Branch on this first.
finalVariables
[String: VariableValue]
Every flow variable and its value at the end. Read user choices captured by the flow.
screensVisited
[String]
Screen node ids in the order the user saw them.
durationMs
Int
How long the flow was on screen, in milliseconds.
experimentAssignments
[String: String]
Experiment id to assigned variant id, for any experiment the user was bucketed into.
.completed means the flow reached its end (a closeFlow action or the final screen). This is the success case.
.dismissed means the user left before finishing (swiped away, a back action off the first screen). This is not a completion; do not treat it as one.
.error means FlowPilot had nothing presentable, or the presentation failed. Read error for the reason. The never-throws fallback overload returns this when it falls back to your native UI.
finalVariables maps each variable key to a VariableValue, an enum with typed accessors. Use the accessor for the type you expect; it returns nil if the value is absent or the wrong type.
Accessor
Returns
.stringValue
String?
.numberValue
Double?
.intValue
Int?
.boolValue
Bool?
.stringListValue
[String]?
.numberListValue
[Double]?
.booleanListValue
[Bool]?
func handle(_ result: FlowResult) { switch result.outcome { case .completed: // Read a choice the flow captured into a variable. if let plan = result.finalVariables["selected_plan"]?.stringValue { applySelectedPlan(plan) } // Attribute the experiment variant the user was shown. if let variant = result.experimentAssignments["paywall_pricing_test"] { analytics.setProperty("paywall_variant", variant) } case .dismissed: // User closed the flow early. Not a completion. analytics.track("onboarding_abandoned", ["screens": result.screensVisited.count]) case .error: // Nothing to present, or presentation failed. log("Flow error: \(result.error?.message ?? "unknown")") }}
For analytics and errors that span flows, set closures on the SDK once. These are the confirmed, public callbacks:
// Forward every automatic analytics event to your own analytics.FlowPilot.shared?.setAnalyticsCallback { event in analytics.track(event.eventName, event.properties)}// Receive SDK-level errors.FlowPilot.shared?.setErrorCallback { error in log("FlowPilot error: \(error)")}
See Analytics integration for the AnalyticsEvent shape and Error handling for error codes.There is no global flow-completion or flow-dismissal callback to register. Learn how a specific presentation ended from its FlowResult (returned, delivered to completion, or passed to onResult), not from a global callback.
A FlowPilotDelegate protocol (flowPilotDidComplete / flowPilotDidDismiss / flowPilotDidFail) is declared public, but FlowPilot exposes no property to set a delegate and never calls these methods. It is not usable today. Use the FlowResult and the setAnalyticsCallback / setErrorCallback closures above.
Treating .dismissed as success. A dismissed flow did not complete. Only .completed means the user reached the end.
Assuming a variable exists.finalVariables["key"] is optional, and so is the typed accessor. Always use optional binding or a default; never force-unwrap.
Ignoring error on .error. When outcome == .error, error carries the reason (for example flow_not_found, timeout). Log or branch on it.
Reading the wrong variable type..boolValue on a string variable returns nil (unless the string coerces). Match the accessor to the variable’s declared type.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"FlowPilot","colors":{"primary":"#FF2056","light":"#FF7589","dark":"#DC1949"},"logo":{"light":"https://mintcdn.com/flowpilot/jc9MUwijUACjoaV2/images/logo-light.svg?fit=max\u0026auto=format\u0026n=jc9MUwijUACjoaV2\u0026q=85\u0026s=cf31b90b95645750d0ed716de42ed079","dark":"https://mintcdn.com/flowpilot/jc9MUwijUACjoaV2/images/logo-dark.svg?fit=max\u0026auto=format\u0026n=jc9MUwijUACjoaV2\u0026q=85\u0026s=6a5bea7879f25768e8da60fcf2882904"},"favicon":"https://mintcdn.com/flowpilot/jc9MUwijUACjoaV2/images/favicon.svg?fit=max\u0026auto=format\u0026n=jc9MUwijUACjoaV2\u0026q=85\u0026s=c9269f355dd5a4589e6fe48cf2dfef7d","appearance":{"default":"system"},"background":{"color":{"light":"#FAFAFB","dark":"#0E1116"}},"contextual":{"options":["copy","view","assistant","chatgpt","claude","perplexity","grok","aistudio","devin","mcp","cursor","vscode","devin-mcp","download-spec","download-pdf"],"display":"header"},"styling":{"latex":false},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"flowpilot","hasAudioNarration":false,"actualSubdomain":"flowpilot","customDomains":["docs.getflowpilot.io"],"gitSource":{"type":"github","owner":"hashamghuffary","repo":"flowpilot-docs","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"chroma":{"collectionId":"17b65517-d7ae-4da0-8b15-957b33e9d4b5","liveDeploymentHistoryId":"6a7f9527ea233c90463d8a55","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6a7f9527ea233c90463d8a55"},"entitlements":{"AI_CHAT":{"status":"DISABLED"}},"buildId":"6ae95918021c491c8f5ae672:success","clientVersion":"0.0.4067","searchFilterCounts":[{"language":"default","tag":"Flow Editor","count":24},{"language":"default","tag":"iOS SDK","count":20},{"language":"default","tag":"Expo SDK","count":19},{"language":"default","tag":"Dashboard","count":16},{"language":"default","tag":"Reference","count":13},{"language":"default","tag":"Customization","count":10},{"language":"default","tag":"Getting started","count":8},{"language":"default","tag":"Presenting flows","count":7},{"language":"default","tag":"Paywalls","count":7},{"language":"default","tag":"Offline \u0026 performance","count":6}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"ios-sdk/results-and-outcomes","slug":"/ios-sdk/results-and-outcomes","pageMetadata":{"title":"Results and outcomes","description":"Every flow presentation resolves to a FlowResult describing how the flow ended and what state it produced.","href":"/ios-sdk/results-and-outcomes"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Every flow presentation resolves to a FlowResult describing how the flow ended and what state it produced.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,li:`li`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,..._provideComponents(),...props.components},{CodeBlock,Heading,Table,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Table)_missingMdxReference(`Table`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsxs(_components.p,{children:[`Every way you present a flow ends with a `,_jsx(_components.code,{children:`FlowResult`}),`. It tells you how the flow finished, which screens the user saw, what variables the flow captured, and which experiment variant (if any) the user got. Read it to branch your app logic, persist a captured choice, or attribute a conversion.`]}),`\n`,_jsxs(_components.p,{children:[`You get a `,_jsx(_components.code,{children:`FlowResult`}),` from:`]}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`the awaited return of `,_jsx(_components.a,{href:`/ios-sdk/presenting-placements`,children:_jsx(_components.code,{children:`presentPlacement(_:from:options:)`})}),`,`]}),`\n`,_jsxs(_components.li,{children:[`the `,_jsx(_components.code,{children:`completion`}),` of the callback overload,`]}),`\n`,_jsxs(_components.li,{children:[`the `,_jsx(_components.code,{children:`fallback`}),` overload’s return value,`]}),`\n`,_jsxs(_components.li,{children:[`the `,_jsx(_components.code,{children:`onResult`}),` closure of `,_jsx(_components.a,{href:`/ios-sdk/swiftui`,children:_jsx(_components.code,{children:`.flowPresenter`})}),`,`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`await session.waitForCompletion()`}),` when embedding a `,_jsx(_components.code,{children:`FlowPresenterView`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`the-flowresult-shape`,children:`The FlowResult shape`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`14`,language:`swift`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`swift`,children:_jsxs(_components.code,{language:`swift`,numberOfLines:`14`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`public`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` struct`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#4EC9B0`},children:` FlowResult`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:`Sendable `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` public`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` let`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` outcome: FlowOutcome`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` public`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` let`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` finalVariables: [`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:`String`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: VariableValue]`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` public`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` let`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` screensVisited: [`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:`String`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` public`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` let`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` durationMs: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:`Int`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` public`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` let`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` experimentAssignments: [`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:`String`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:`String`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` public`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` let`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` error: FlowPilotError`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`?`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`public`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` enum`}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#4EC9B0`},children:` FlowOutcome`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:`String`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:`Sendable `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` case`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` completed`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` case`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` dismissed`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` case`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` error`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Field`}),_jsx(_components.th,{children:`Type`}),_jsx(_components.th,{children:`What it tells you`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`outcome`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`FlowOutcome`})}),_jsxs(_components.td,{children:[`How the flow ended: `,_jsx(_components.code,{children:`.completed`}),`, `,_jsx(_components.code,{children:`.dismissed`}),`, or `,_jsx(_components.code,{children:`.error`}),`. Branch on this first.`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`finalVariables`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`[String: VariableValue]`})}),_jsx(_components.td,{children:`Every flow variable and its value at the end. Read user choices captured by the flow.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`screensVisited`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`[String]`})}),_jsx(_components.td,{children:`Screen node ids in the order the user saw them.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`durationMs`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`Int`})}),_jsx(_components.td,{children:`How long the flow was on screen, in milliseconds.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`experimentAssignments`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`[String: String]`})}),_jsx(_components.td,{children:`Experiment id to assigned variant id, for any experiment the user was bucketed into.`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`error`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`FlowPilotError?`})}),_jsxs(_components.td,{children:[`Set when `,_jsx(_components.code,{children:`outcome == .error`}),`. `,_jsx(_components.code,{children:`nil`}),` otherwise.`]})]})]})]}),`\n`,_jsx(Heading,{level:`3`,id:`outcomes`,children:`Outcomes`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:_jsx(_components.code,{children:`.completed`})}),` means the flow reached its end (a `,_jsx(_components.code,{children:`closeFlow`}),` action or the final screen). This is the success case.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:_jsx(_components.code,{children:`.dismissed`})}),` means the user left before finishing (swiped away, a back action off the first screen). This is not a completion; do not treat it as one.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:_jsx(_components.code,{children:`.error`})}),` means FlowPilot had nothing presentable, or the presentation failed. Read `,_jsx(_components.code,{children:`error`}),` for the reason. The never-throws `,_jsx(_components.a,{href:`/ios-sdk/presenting-placements`,children:_jsx(_components.code,{children:`fallback`})}),` overload returns this when it falls back to your native UI.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`reading-captured-variables`,children:`Reading captured variables`}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`finalVariables`}),` maps each variable key to a `,_jsx(_components.code,{children:`VariableValue`}),`, an enum with typed accessors. Use the accessor for the type you expect; it returns `,_jsx(_components.code,{children:`nil`}),` if the value is absent or the wrong type.`]}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Accessor`}),_jsx(_components.th,{children:`Returns`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`.stringValue`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`String?`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`.numberValue`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`Double?`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`.intValue`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`Int?`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`.boolValue`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`Bool?`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`.stringListValue`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`[String]?`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`.numberListValue`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`[Double]?`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`.booleanListValue`})}),_jsx(_components.td,{children:_jsx(_components.code,{children:`[Bool]?`})})]})]})]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`21`,language:`swift`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`swift`,children:_jsxs(_components.code,{language:`swift`,numberOfLines:`21`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`func`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` handle`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`_`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` result`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: FlowResult) {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` switch`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` result.outcome {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` case`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` .`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`completed`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // Read a choice the flow captured into a variable.`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` if`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` let`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` plan `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` result.finalVariables[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"selected_plan\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`?`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#9CDCFE`},children:`stringValue`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:` applySelectedPlan`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(plan)`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // Attribute the experiment variant the user was shown.`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` if`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:` let`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` variant `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` result.experimentAssignments[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"paywall_pricing_test\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`] {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` analytics.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:`setProperty`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"paywall_variant\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, variant)`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` case`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` .`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`dismissed`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // User closed the flow early. Not a completion.`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` analytics.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:`track`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"onboarding_abandoned\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, [`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"screens\"`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`:`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` result.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`screensVisited`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#9CDCFE`},children:`count`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`])`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` case`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` .`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#9CDCFE`},children:`error`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // Nothing to present, or presentation failed.`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:` log`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"Flow error: `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`\\\\(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#D4D4D4`},children:`result.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#9CDCFE`},children:`error`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`?`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`message`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` ??`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"unknown\"`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`)`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`completion-callbacks-on-the-sdk`,children:`Completion callbacks on the SDK`}),`\n`,_jsx(_components.p,{children:`For analytics and errors that span flows, set closures on the SDK once. These are the confirmed, public callbacks:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`9`,language:`swift`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`swift`,children:_jsxs(_components.code,{language:`swift`,numberOfLines:`9`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// Forward every automatic analytics event to your own analytics.`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`FlowPilot.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`shared`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`?`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:`setAnalyticsCallback`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` { event `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`in`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` analytics.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:`track`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(event.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`eventName`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, event.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`properties`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// Receive SDK-level errors.`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`FlowPilot.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`shared`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`?`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:`setErrorCallback`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` { error `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`in`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:` log`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"FlowPilot error: `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`\\\\(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#D4D4D4`},children:`error`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`)`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`See `,_jsx(_components.a,{href:`/ios-sdk/analytics`,children:`Analytics integration`}),` for the `,_jsx(_components.code,{children:`AnalyticsEvent`}),` shape and `,_jsx(_components.a,{href:`/ios-sdk/error-handling`,children:`Error handling`}),` for error codes.`]}),`\n`,_jsxs(_components.p,{children:[`There is `,_jsx(_components.strong,{children:`no global flow-completion or flow-dismissal callback`}),` to register. Learn how a specific presentation ended from its `,_jsx(_components.code,{children:`FlowResult`}),` (returned, delivered to `,_jsx(_components.code,{children:`completion`}),`, or passed to `,_jsx(_components.code,{children:`onResult`}),`), not from a global callback.`]}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`A `,_jsx(_components.code,{children:`FlowPilotDelegate`}),` protocol (`,_jsx(_components.code,{children:`flowPilotDidComplete`}),` / `,_jsx(_components.code,{children:`flowPilotDidDismiss`}),` / `,_jsx(_components.code,{children:`flowPilotDidFail`}),`) is declared `,_jsx(_components.code,{children:`public`}),`, but `,_jsx(_components.code,{children:`FlowPilot`}),` exposes no property to set a delegate and never calls these methods. It is not usable today. Use the `,_jsx(_components.code,{children:`FlowResult`}),` and the `,_jsx(_components.code,{children:`setAnalyticsCallback`}),` / `,_jsx(_components.code,{children:`setErrorCallback`}),` closures above.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`common-mistakes`,children:`Common mistakes`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsxs(_components.strong,{children:[`Treating `,_jsx(_components.code,{children:`.dismissed`}),` as success.`]}),` A dismissed flow did not complete. Only `,_jsx(_components.code,{children:`.completed`}),` means the user reached the end.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Assuming a variable exists.`}),` `,_jsx(_components.code,{children:`finalVariables[\"key\"]`}),` is optional, and so is the typed accessor. Always use optional binding or a default; never force-unwrap.`]}),`\n`,_jsxs(_components.li,{children:[_jsxs(_components.strong,{children:[`Ignoring `,_jsx(_components.code,{children:`error`}),` on `,_jsx(_components.code,{children:`.error`}),`.`]}),` When `,_jsx(_components.code,{children:`outcome == .error`}),`, `,_jsx(_components.code,{children:`error`}),` carries the reason (for example `,_jsx(_components.code,{children:`flow_not_found`}),`, `,_jsx(_components.code,{children:`timeout`}),`). Log or branch on it.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Reading the wrong variable type.`}),` `,_jsx(_components.code,{children:`.boolValue`}),` on a string variable returns `,_jsx(_components.code,{children:`nil`}),` (unless the string coerces). Match the accessor to the variable’s declared type.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`related-pages`,children:`Related pages`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:_jsx(_components.a,{href:`/ios-sdk/presenting-placements`,children:`Presenting placements (UIKit)`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.a,{href:`/ios-sdk/swiftui`,children:`SwiftUI integration`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.a,{href:`/ios-sdk/variables-and-context`,children:`Variables and SDK context`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.a,{href:`/ios-sdk/analytics`,children:`Analytics integration`})}),`\n`,_jsx(_components.li,{children:_jsx(_components.a,{href:`/ios-sdk/error-handling`,children:`Error handling`})}),`\n`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Results and outcomes","description":"Every flow presentation resolves to a FlowResult describing how the flow ended and what state it produced.","href":"/ios-sdk/results-and-outcomes"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"The FlowResult shape","slug":"the-flowresult-shape","depth":2,"children":[{"title":"Outcomes","slug":"outcomes","depth":3,"children":[]}]},{"title":"Reading captured variables","slug":"reading-captured-variables","depth":2,"children":[]},{"title":"Completion callbacks on the SDK","slug":"completion-callbacks-on-the-sdk","depth":2,"children":[]},{"title":"Common mistakes","slug":"common-mistakes","depth":2,"children":[]},{"title":"Related pages","slug":"related-pages","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"flowpilot","siteName":"FlowPilot","title":"Results and outcomes - FlowPilot","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-06-18T11:59:58.893Z","originalFileLocation":"ios-sdk/results-and-outcomes.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Every flow presentation resolves to a FlowResult describing how the flow ended and what state it produced.\">\u003cmeta data-mint-head name=\"application-name\" content=\"FlowPilot\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/flowpilot/iksThPQZHoooCVt7/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/flowpilot/iksThPQZHoooCVt7/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/flowpilot/iksThPQZHoooCVt7/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/flowpilot/iksThPQZHoooCVt7/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/flowpilot/iksThPQZHoooCVt7/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/flowpilot/iksThPQZHoooCVt7/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/flowpilot/iksThPQZHoooCVt7/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/flowpilot/iksThPQZHoooCVt7/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/flowpilot/iksThPQZHoooCVt7/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Results and outcomes - FlowPilot\">\u003cmeta data-mint-head property=\"og:description\" content=\"Every flow presentation resolves to a FlowResult describing how the flow ended and what state it produced.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"FlowPilot\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.getflowpilot.io/ios-sdk/results-and-outcomes\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://flowpilot.mintlify.app/_mintlify/api/og/v2?division=Presenting+flows\u0026amp;title=Results+and+outcomes\u0026amp;description=Every+flow+presentation+resolves+to+a+FlowResult+describing+how+the+flow+ended+and+what+state+it+produced.\u0026amp;theme=e6dc96b53e3dfbaad1d020df\u0026amp;signature=53f0ec5b49f8fcceaf7dc28eb97daf7dd100eda8a26c11ceb4d3aa8d859d8530\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Results and outcomes - FlowPilot\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Every flow presentation resolves to a FlowResult describing how the flow ended and what state it produced.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://flowpilot.mintlify.app/_mintlify/api/og/v2?division=Presenting+flows\u0026amp;title=Results+and+outcomes\u0026amp;description=Every+flow+presentation+resolves+to+a+FlowResult+describing+how+the+flow+ended+and+what+state+it+produced.\u0026amp;theme=e6dc96b53e3dfbaad1d020df\u0026amp;signature=53f0ec5b49f8fcceaf7dc28eb97daf7dd100eda8a26c11ceb4d3aa8d859d8530\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/flowpilot/iksThPQZHoooCVt7/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"FlowPilot\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#FF2056\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.getflowpilot.io/ios-sdk/results-and-outcomes\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/ios-sdk/results-and-outcomes.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.getflowpilot.io/#organization\",\"name\":\"FlowPilot\",\"url\":\"https://docs.getflowpilot.io\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/flowpilot/jc9MUwijUACjoaV2/images/logo-light.svg?fit=max\u0026auto=format\u0026n=jc9MUwijUACjoaV2\u0026q=85\u0026s=cf31b90b95645750d0ed716de42ed079\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.getflowpilot.io#website\",\"name\":\"FlowPilot\",\"url\":\"https://docs.getflowpilot.io\",\"publisher\":{\"@id\":\"https://docs.getflowpilot.io/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.getflowpilot.io/ios-sdk/results-and-outcomes#webpage\",\"url\":\"https://docs.getflowpilot.io/ios-sdk/results-and-outcomes\",\"name\":\"Results and outcomes\",\"description\":\"Every flow presentation resolves to a FlowResult describing how the flow ended and what state it produced.\",\"dateModified\":\"2026-06-18T11:59:58.893Z\",\"isPartOf\":{\"@id\":\"https://docs.getflowpilot.io#website\"},\"breadcrumb\":{\"@id\":\"https://docs.getflowpilot.io/ios-sdk/results-and-outcomes#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.getflowpilot.io/ios-sdk/results-and-outcomes#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Presenting flows\",\"item\":\"https://docs.getflowpilot.io/ios-sdk/presenting-placements\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Results and outcomes\",\"item\":\"https://docs.getflowpilot.io/ios-sdk/results-and-outcomes\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.getflowpilot.io/ios-sdk/results-and-outcomes#article\",\"headline\":\"Results and outcomes\",\"name\":\"Results and outcomes\",\"description\":\"Every flow presentation resolves to a FlowResult describing how the flow ended and what state it produced.\",\"url\":\"https://docs.getflowpilot.io/ios-sdk/results-and-outcomes\",\"mainEntityOfPage\":{\"@id\":\"https://docs.getflowpilot.io/ios-sdk/results-and-outcomes#webpage\"},\"dateModified\":\"2026-06-18T11:59:58.893Z\",\"publisher\":{\"@id\":\"https://docs.getflowpilot.io/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.getflowpilot.io#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"FlowPilot\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"FlowPilot","nav":{"global":null,"tabs":[{"tab":"Get Started","pages":[{"title":"Get Started","href":"/get-started"}]},{"tab":"Dashboard","pages":[{"title":"Dashboard","href":"/dashboard"}]},{"tab":"Flow Editor","pages":[{"title":"Flow Editor","href":"/editor"}]},{"tab":"iOS SDK","groups":[{"group":"Getting started","pages":[{"title":"FlowPilot iOS SDK","href":"/ios-sdk"},{"title":"Installation","href":"/ios-sdk/installation"},{"title":"Configuration","href":"/ios-sdk/configuration"},{"title":"iOS quickstart","href":"/ios-sdk/quickstart"}]},{"group":"Presenting flows","pages":[{"title":"Presenting placements","href":"/ios-sdk/presenting-placements"},{"title":"SwiftUI integration","description":"Present FlowPilot flows declaratively with a FlowSession and the .flowPresenter modifier, or embed a FlowPresenterView directly.","href":"/ios-sdk/swiftui"},{"title":"Results and outcomes","href":"/ios-sdk/results-and-outcomes"},{"title":"Prefetching and readiness","description":"Warm up placements ahead of time so a flow appears instantly when you need it.","href":"/ios-sdk/prefetching"}]},{"group":"Data \u0026 context","pages":[{"title":"Variables and SDK context","href":"/ios-sdk/variables-and-context"},{"title":"Conversions and revenue","href":"/ios-sdk/conversions"}]},{"group":"Customization","pages":[{"title":"Custom components","href":"/ios-sdk/custom-components"},{"title":"Custom screens","href":"/ios-sdk/custom-screens"},{"title":"User identity","href":"/ios-sdk/user-identity"},{"title":"Analytics integration","href":"/ios-sdk/analytics"},{"title":"Error handling","href":"/ios-sdk/error-handling"}]},{"group":"Offline \u0026 performance","pages":[{"title":"Caching","href":"/ios-sdk/caching"},{"title":"Offline and bundled flows","href":"/ios-sdk/offline-bundled-flows"},{"title":"Media preloading","href":"/ios-sdk/media-preloading"}]},{"group":"Reference","pages":[{"title":"API reference","href":"/ios-sdk/api-reference"},{"title":"Troubleshooting","href":"/ios-sdk/troubleshooting"}]}]},{"tab":"Expo SDK","pages":[{"title":"Expo SDK","href":"/expo-sdk"}]},{"tab":"Paywalls","pages":[{"title":"Paywalls","href":"/paywalls"}]},{"tab":"Reference","pages":[{"title":"Reference","href":"/reference/flow-schema"}]}]},"basePath":"","title":"Results and outcomes - FlowPilot","buildId":"dpl_9VVk5y1P8k1ATeJguVngy9Q3cmbD","deploymentId":"dpl_9VVk5y1P8k1ATeJguVngy9Q3cmbD","dynamics":[],"chunks":[]}