[{"data":1,"prerenderedAt":4988},["ShallowReactive",2],{"navigation_docs":3,"-sdks-mobile-swift":244,"-sdks-mobile-swift-surround":4983},[4,51,78,229],{"title":5,"icon":6,"modifiedAt":7,"path":8,"stem":9,"children":10,"page":6},"Getting Started",false,"2026-04-30T19:15:33.000Z","\u002Fgetting-started","1.getting-started",[11,16,21,26,31,36,41,46],{"title":12,"path":13,"stem":14,"icon":15},"Quickstart","\u002Fgetting-started\u002Fquickstart","1.getting-started\u002F1.quickstart","i-lucide-fast-forward",{"title":17,"path":18,"stem":19,"icon":20},"Core Concepts","\u002Fgetting-started\u002Fcore-concepts","1.getting-started\u002F2.core-concepts","i-lucide-workflow",{"title":22,"path":23,"stem":24,"icon":25},"Configs Anatomy","\u002Fgetting-started\u002Fconfigs","1.getting-started\u002F3.configs","i-lucide-file-cog",{"title":27,"path":28,"stem":29,"icon":30},"Architecture","\u002Fgetting-started\u002Farchitecture","1.getting-started\u002F4.architecture","i-lucide-layers",{"title":32,"path":33,"stem":34,"icon":35},"JSON Schema Validation","\u002Fgetting-started\u002Fjson-schema-validation","1.getting-started\u002F5.json-schema-validation","i-lucide-braces",{"title":37,"path":38,"stem":39,"icon":40},"Testing Rules","\u002Fgetting-started\u002Ftesting-targeting-rules","1.getting-started\u002F6.testing-targeting-rules","i-lucide-flask-conical",{"title":42,"path":43,"stem":44,"icon":45},"Segments","\u002Fgetting-started\u002Fsegments","1.getting-started\u002F7.segments","i-lucide-squares-intersect",{"title":47,"path":48,"stem":49,"icon":50},"Pricing & Billing","\u002Fgetting-started\u002Fpricing-and-billing","1.getting-started\u002F8.pricing-and-billing","i-lucide-credit-card",{"title":52,"modifiedAt":53,"defaultOpen":54,"path":55,"stem":56,"children":57,"page":6},"Monitoring","2026-09-24T23:33:20.000Z",true,"\u002Fmonitoring","2.monitoring",[58,63,68,73],{"title":59,"path":60,"stem":61,"icon":62},"Activity","\u002Fmonitoring\u002Factivity","2.monitoring\u002F1.activity","i-lucide-activity",{"title":64,"path":65,"stem":66,"icon":67},"Lifecycle","\u002Fmonitoring\u002Flifecycle","2.monitoring\u002F2.lifecycle","i-lucide-recycle",{"title":69,"path":70,"stem":71,"icon":72},"Alerts","\u002Fmonitoring\u002Falerts","2.monitoring\u002F3.alerts","i-lucide-bell",{"title":74,"path":75,"stem":76,"icon":77},"Dynamic Detection","\u002Fmonitoring\u002Fdynamic-detection","2.monitoring\u002F4.dynamic-detection","i-lucide-hat-glasses",{"title":79,"modifiedAt":53,"defaultOpen":54,"path":80,"stem":81,"children":82,"page":6},"SDKs","\u002Fsdks","3.sdks",[83,88,109,134,150,181,224],{"title":84,"path":85,"stem":86,"icon":87},"Available SDKs","\u002Fsdks\u002Favailable-sdks","3.sdks\u002F1.available-sdks","i-lucide-list",{"title":89,"modifiedAt":53,"icon":90,"defaultOpen":6,"path":91,"stem":92,"children":93,"page":6},"Browser SDKs","i-lucide-monitor","\u002Fsdks\u002Fbrowser","3.sdks\u002F2.browser",[94,99,104],{"title":95,"path":96,"stem":97,"icon":98},"Javascript","\u002Fsdks\u002Fbrowser\u002Fjavascript","3.sdks\u002F2.browser\u002F1.javascript","cd-logos-javascript",{"title":100,"path":101,"stem":102,"icon":103},"React","\u002Fsdks\u002Fbrowser\u002Freact","3.sdks\u002F2.browser\u002F2.react","cd-logos-react-light",{"title":105,"path":106,"stem":107,"icon":108},"Vue","\u002Fsdks\u002Fbrowser\u002Fvue","3.sdks\u002F2.browser\u002F3.vue","cd-logos-vue",{"title":110,"modifiedAt":53,"icon":111,"defaultOpen":6,"path":112,"stem":113,"children":114,"page":6},"Mobile SDKs","i-lucide-smartphone","\u002Fsdks\u002Fmobile","3.sdks\u002F3.mobile",[115,119,124,129],{"title":116,"path":117,"stem":118,"icon":103},"React Native","\u002Fsdks\u002Fmobile\u002Freact-native","3.sdks\u002F3.mobile\u002F1.react-native",{"title":120,"path":121,"stem":122,"icon":123},"Flutter","\u002Fsdks\u002Fmobile\u002Fflutter","3.sdks\u002F3.mobile\u002F2.flutter","cd-logos-flutter",{"title":125,"path":126,"stem":127,"icon":128},"Swift","\u002Fsdks\u002Fmobile\u002Fswift","3.sdks\u002F3.mobile\u002F3.swift","cd-logos-swift",{"title":130,"path":131,"stem":132,"icon":133},"Android","\u002Fsdks\u002Fmobile\u002Fandroid","3.sdks\u002F3.mobile\u002F4.android","cd-logos-android",{"title":135,"modifiedAt":53,"icon":136,"defaultOpen":6,"path":137,"stem":138,"children":139,"page":6},"Meta-framework SDKs","i-lucide-monitor-smartphone","\u002Fsdks\u002Fmeta","3.sdks\u002F4.meta",[140,145],{"title":141,"path":142,"stem":143,"icon":144},"Next.js","\u002Fsdks\u002Fmeta\u002Fnextjs","3.sdks\u002F4.meta\u002F1.nextjs","cd-logos-nextjs",{"title":146,"path":147,"stem":148,"icon":149},"Nuxt","\u002Fsdks\u002Fmeta\u002Fnuxt","3.sdks\u002F4.meta\u002F2.nuxt","cd-logos-nuxt",{"title":151,"modifiedAt":53,"icon":152,"defaultOpen":6,"path":153,"stem":154,"children":155,"page":6},"Server SDKs","i-lucide-server","\u002Fsdks\u002Fserver","3.sdks\u002F5.server",[156,161,166,171,176],{"title":157,"path":158,"stem":159,"icon":160},"Node.js","\u002Fsdks\u002Fserver\u002Fnode-js","3.sdks\u002F5.server\u002F1.node-js","cd-logos-nodejs",{"title":162,"path":163,"stem":164,"icon":165},"Python","\u002Fsdks\u002Fserver\u002Fpython","3.sdks\u002F5.server\u002F2.python","cd-logos-python",{"title":167,"path":168,"stem":169,"icon":170},"Java","\u002Fsdks\u002Fserver\u002Fjava","3.sdks\u002F5.server\u002F3.java","cd-logos-java",{"title":172,"path":173,"stem":174,"icon":175},".NET","\u002Fsdks\u002Fserver\u002Fdotnet","3.sdks\u002F5.server\u002F4.dotnet","cd-logos-dotnet",{"title":177,"path":178,"stem":179,"icon":180},"Go","\u002Fsdks\u002Fserver\u002Fgo","3.sdks\u002F5.server\u002F5.go","cd-logos-go",{"title":182,"modifiedAt":53,"icon":183,"defaultOpen":6,"path":184,"stem":185,"children":186,"page":6},"OpenFeature Providers","cd-logos-openfeature","\u002Fsdks\u002Fopenfeature","3.sdks\u002F6.openfeature",[187,192,196,200,204,208,212,216,220],{"title":188,"path":189,"stem":190,"icon":183,"icons":191},"Web","\u002Fsdks\u002Fopenfeature\u002Fweb","3.sdks\u002F6.openfeature\u002F1.web",[183,98],{"title":125,"path":193,"stem":194,"icon":183,"icons":195},"\u002Fsdks\u002Fopenfeature\u002Fswift","3.sdks\u002F6.openfeature\u002F2.swift",[183,128],{"title":130,"path":197,"stem":198,"icon":183,"icons":199},"\u002Fsdks\u002Fopenfeature\u002Fandroid","3.sdks\u002F6.openfeature\u002F3.android",[183,133],{"title":120,"path":201,"stem":202,"icon":183,"icons":203},"\u002Fsdks\u002Fopenfeature\u002Fflutter","3.sdks\u002F6.openfeature\u002F4.flutter",[183,123],{"title":157,"path":205,"stem":206,"icon":183,"icons":207},"\u002Fsdks\u002Fopenfeature\u002Fnode-js","3.sdks\u002F6.openfeature\u002F5.node-js",[183,160],{"title":162,"path":209,"stem":210,"icon":183,"icons":211},"\u002Fsdks\u002Fopenfeature\u002Fpython","3.sdks\u002F6.openfeature\u002F6.python",[183,165],{"title":167,"path":213,"stem":214,"icon":183,"icons":215},"\u002Fsdks\u002Fopenfeature\u002Fjava","3.sdks\u002F6.openfeature\u002F7.java",[183,170],{"title":172,"path":217,"stem":218,"icon":183,"icons":219},"\u002Fsdks\u002Fopenfeature\u002Fdotnet","3.sdks\u002F6.openfeature\u002F8.dotnet",[183,175],{"title":177,"path":221,"stem":222,"icon":183,"icons":223},"\u002Fsdks\u002Fopenfeature\u002Fgo","3.sdks\u002F6.openfeature\u002F9.go",[183,180],{"title":225,"path":226,"stem":227,"icon":228},"Maven Repository","\u002Fsdks\u002Fmaven-repository","3.sdks\u002F7.maven-repository","i-lucide-package",{"title":230,"modifiedAt":53,"defaultOpen":54,"path":231,"stem":232,"children":233,"page":6},"Integrations","\u002Fintegrations","4.integrations",[234,239],{"title":235,"path":236,"stem":237,"icon":238},"Terraform","\u002Fintegrations\u002Fterraform","4.integrations\u002F1.terraform","cd-logos-terraform",{"title":240,"path":241,"stem":242,"icon":243},"MCP","\u002Fintegrations\u002Fmcp","4.integrations\u002F2.mcp","cd-logos-mcp",{"id":245,"title":246,"body":247,"description":4975,"extension":4976,"links":4977,"meta":4978,"navigation":4980,"path":126,"seo":4981,"stem":127,"__hash__":4982},"docs\u002F3.sdks\u002F3.mobile\u002F3.swift.md","Swift SDK",{"type":248,"value":249,"toc":4946},"minimark",[250,254,258,263,267,318,326,333,337,347,355,371,378,548,552,566,661,664,668,690,696,949,959,964,970,976,982,997,1100,1105,1119,1122,1188,1208,1211,1386,1390,1396,1527,1616,1620,1638,1841,1847,1925,1946,2058,2066,2139,2264,2271,2275,2281,2293,2427,2441,2548,2552,2563,2694,2703,2774,2778,2802,2960,2964,2972,2986,3168,3177,3181,3184,3329,3335,3460,3470,3476,3628,3643,3647,3650,3654,3669,3674,3701,3707,3737,3744,3756,3764,3769,3772,3778,3782,3793,3890,3900,4123,4139,4143,4152,4382,4391,4394,4436,4474,4478,4635,4654,4837,4841,4862,4866,4942],[251,252],"div",{"hidden":54,"dataTitleIcon":253},"swift",[255,256],"external-badges",{"repo":257},"configdirector-swift-sdk",[259,260,262],"h2",{"id":261},"introduction","Introduction",[264,265,266],"p",{},"The Swift SDK is intended to be used by Apple platform applications. It evaluates your configs against a user context, keeps them current as they change in the dashboard, and hands SwiftUI values it can re-render from.",[268,269,270,283],"table",{},[271,272,273],"thead",{},[274,275,276,280],"tr",{},[277,278,279],"th",{},"Platform",[277,281,282],{},"Minimum",[284,285,286,295,303,310],"tbody",{},[274,287,288,292],{},[289,290,291],"td",{},"iOS \u002F iPadOS",[289,293,294],{},"15.0",[274,296,297,300],{},[289,298,299],{},"macOS",[289,301,302],{},"12.0",[274,304,305,308],{},[289,306,307],{},"tvOS",[289,309,294],{},[274,311,312,315],{},[289,313,314],{},"watchOS",[289,316,317],{},"8.0",[264,319,320,321,325],{},"Building it requires Swift 6.0 or newer. The package is built in Swift 6 language mode under strict concurrency and every public type is ",[322,323,324],"code",{},"Sendable",", so the client can be shared across tasks and actors without wrapping it.",[264,327,328,329,332],{},"Config evaluation is synchronous and reads config state the client already holds in memory, which is what makes it safe to call from a SwiftUI ",[322,330,331],{},"body",". Telemetry about those evaluations is aggregated and reported on its own task, so evaluating a config never waits on the network.",[259,334,336],{"id":335},"installation","Installation",[264,338,339,340],{},"The SDK is distributed through Swift Package Manager from its repository: ",[341,342,343],"a",{"href":343,"rel":344,"target":346},"https:\u002F\u002Fgithub.com\u002FConfigDirector\u002Fconfigdirector-swift-sdk",[345],"noopener","_blank",[264,348,349,350,354],{},"In Xcode, go to ",[351,352,353],"strong",{},"File → Add Package Dependencies…"," and enter the package URL:",[356,357,362],"pre",{"className":358,"code":359,"language":360,"meta":361,"style":361},"language-txt shiki shiki-themes material-theme-lighter github-light github-dark","https:\u002F\u002Fgithub.com\u002FConfigDirector\u002Fconfigdirector-swift-sdk\n","txt","",[322,363,364],{"__ignoreMap":361},[365,366,369],"span",{"class":367,"line":368},"line",1,[365,370,359],{},[264,372,373,374,377],{},"To add it to a Swift package instead, declare it in ",[322,375,376],{},"Package.swift",":",[356,379,382],{"className":380,"code":381,"filename":376,"language":253,"meta":361,"style":361},"language-swift shiki shiki-themes material-theme-lighter github-light github-dark","dependencies: [\n    .package(url: \"https:\u002F\u002Fgithub.com\u002FConfigDirector\u002Fconfigdirector-swift-sdk\", from: \"1.7.0\"),\n],\ntargets: [\n    .target(\n        name: \"YourTarget\",\n        dependencies: [.product(name: \"ConfigDirector\", package: \"configdirector-swift-sdk\")]\n    ),\n]\n",[322,383,384,396,446,452,462,473,490,535,543],{"__ignoreMap":361},[365,385,386,390,393],{"class":367,"line":368},[365,387,389],{"class":388},"su5hD","dependencies",[365,391,377],{"class":392},"smGrS",[365,394,395],{"class":388}," [\n",[365,397,399,402,406,410,413,415,419,422,425,428,431,433,435,438,440,443],{"class":367,"line":398},2,[365,400,401],{"class":388},"    .",[365,403,405],{"class":404},"sptTA","package",[365,407,409],{"class":408},"sP7_E","(",[365,411,412],{"class":404},"url",[365,414,377],{"class":408},[365,416,418],{"class":417},"sjJ54"," \"",[365,420,343],{"class":421},"s_sjI",[365,423,424],{"class":417},"\"",[365,426,427],{"class":388},", ",[365,429,430],{"class":404},"from",[365,432,377],{"class":408},[365,434,418],{"class":417},[365,436,437],{"class":421},"1.7.0",[365,439,424],{"class":417},[365,441,442],{"class":408},")",[365,444,445],{"class":388},",\n",[365,447,449],{"class":367,"line":448},3,[365,450,451],{"class":388},"],\n",[365,453,455,458,460],{"class":367,"line":454},4,[365,456,457],{"class":388},"targets",[365,459,377],{"class":392},[365,461,395],{"class":388},[365,463,465,467,470],{"class":367,"line":464},5,[365,466,401],{"class":388},[365,468,469],{"class":404},"target",[365,471,472],{"class":408},"(\n",[365,474,476,479,481,483,486,488],{"class":367,"line":475},6,[365,477,478],{"class":404},"        name",[365,480,377],{"class":408},[365,482,418],{"class":417},[365,484,485],{"class":421},"YourTarget",[365,487,424],{"class":417},[365,489,445],{"class":388},[365,491,493,496,498,501,504,506,509,511,513,516,518,520,522,524,526,528,530,532],{"class":367,"line":492},7,[365,494,495],{"class":404},"        dependencies",[365,497,377],{"class":408},[365,499,500],{"class":388}," [.",[365,502,503],{"class":404},"product",[365,505,409],{"class":408},[365,507,508],{"class":404},"name",[365,510,377],{"class":408},[365,512,418],{"class":417},[365,514,515],{"class":421},"ConfigDirector",[365,517,424],{"class":417},[365,519,427],{"class":388},[365,521,405],{"class":404},[365,523,377],{"class":408},[365,525,418],{"class":417},[365,527,257],{"class":421},[365,529,424],{"class":417},[365,531,442],{"class":408},[365,533,534],{"class":388},"]\n",[365,536,538,541],{"class":367,"line":537},8,[365,539,540],{"class":408},"    )",[365,542,445],{"class":388},[365,544,546],{"class":367,"line":545},9,[365,547,534],{"class":388},[259,549,551],{"id":550},"configure-and-initialize-the-client","Configure and initialize the client",[553,554,555,563],"ol",{},[556,557,558,559,562],"li",{},"Create an instance of the client providing your client SDK key. You can retrieve a client SDK key for each environment under ",[322,560,561],{},"SDK keys"," in the dashboard's navigation panel.",[556,564,565],{},"Initialize the client to initiate its connection lifecycle.",[356,567,570],{"className":380,"code":568,"filename":569,"language":253,"meta":361,"style":361},"import ConfigDirector\n\n\u002F\u002F Creating the client makes no network calls. It throws only when the SDK key is\n\u002F\u002F blank or a custom base URL is invalid.\nlet client = try ConfigDirectorClient(clientSDKKey: \"YOUR-CLIENT-SDK-KEY\")\n\n\u002F\u002F Connects and waits until config values are received, or until it times out.\n\u002F\u002F After a timeout the client keeps trying to connect in the background.\nawait client.initialize()\n","ConfigDirectorSetup.swift",[322,571,572,582,587,593,598,633,637,642,647],{"__ignoreMap":361},[365,573,574,578],{"class":367,"line":368},[365,575,577],{"class":576},"sVHd0","import",[365,579,581],{"class":580},"sbgvK"," ConfigDirector\n",[365,583,584],{"class":367,"line":398},[365,585,586],{"emptyLinePlaceholder":54},"\n",[365,588,589],{"class":367,"line":448},[365,590,592],{"class":591},"sutJx","\u002F\u002F Creating the client makes no network calls. It throws only when the SDK key is\n",[365,594,595],{"class":367,"line":454},[365,596,597],{"class":591},"\u002F\u002F blank or a custom base URL is invalid.\n",[365,599,600,604,607,610,613,616,618,621,623,625,628,630],{"class":367,"line":464},[365,601,603],{"class":602},"sw1J6","let",[365,605,606],{"class":388}," client ",[365,608,609],{"class":392},"=",[365,611,612],{"class":576}," try",[365,614,615],{"class":404}," ConfigDirectorClient",[365,617,409],{"class":408},[365,619,620],{"class":404},"clientSDKKey",[365,622,377],{"class":408},[365,624,418],{"class":417},[365,626,627],{"class":421},"YOUR-CLIENT-SDK-KEY",[365,629,424],{"class":417},[365,631,632],{"class":408},")\n",[365,634,635],{"class":367,"line":475},[365,636,586],{"emptyLinePlaceholder":54},[365,638,639],{"class":367,"line":492},[365,640,641],{"class":591},"\u002F\u002F Connects and waits until config values are received, or until it times out.\n",[365,643,644],{"class":367,"line":537},[365,645,646],{"class":591},"\u002F\u002F After a timeout the client keeps trying to connect in the background.\n",[365,648,649,652,655,658],{"class":367,"line":545},[365,650,651],{"class":576},"await",[365,653,654],{"class":388}," client.",[365,656,657],{"class":404},"initialize",[365,659,660],{"class":408},"()\n",[264,662,663],{},"The client is thread safe. Create one and share it for the lifetime of the app.",[665,666,667],"note",{},"Before the client is initialized, config values will evaluate to the default value provided in code.",[264,669,670,671,674,675,678,679,682,683,685,686,689],{},"The initializer throws a ",[322,672,673],{},"ConfigDirectorError"," in only two cases, both of which are programming errors rather than runtime conditions: ",[322,676,677],{},"missingClientSDKKey"," when the key is blank, and ",[322,680,681],{},"invalidBaseURL"," when a custom base URL is not absolute. Connection failures are not thrown — ",[322,684,657],{}," returns normally whether or not config state arrived, and ",[322,687,688],{},"isReady"," tells you which happened.",[264,691,692,693,377],{},"Most applications create a single client instance, initialize it during startup, and let it live for the lifetime of the app. In a SwiftUI app that usually means owning it in the ",[322,694,695],{},"App",[356,697,700],{"className":380,"code":698,"filename":699,"language":253,"meta":361,"style":361},"import ConfigDirector\nimport SwiftUI\n\n@main\nstruct MyApp: App {\n    @State private var client = try? ConfigDirectorClient(clientSDKKey: \"YOUR-CLIENT-SDK-KEY\")\n\n    var body: some Scene {\n        WindowGroup {\n            ContentView()\n                .environment(\\.configDirectorClient, client)\n                .task {\n                    await client?.initialize(context: ConfigDirectorContext(id: \"user-123\"))\n                }\n        }\n    }\n}\n\nextension EnvironmentValues {\n    @Entry var configDirectorClient: ConfigDirectorClient?\n}\n","MyApp.swift",[322,701,702,708,715,719,728,744,783,787,803,811,819,835,845,888,894,900,906,912,917,928,944],{"__ignoreMap":361},[365,703,704,706],{"class":367,"line":368},[365,705,577],{"class":576},[365,707,581],{"class":580},[365,709,710,712],{"class":367,"line":398},[365,711,577],{"class":576},[365,713,714],{"class":580}," SwiftUI\n",[365,716,717],{"class":367,"line":448},[365,718,586],{"emptyLinePlaceholder":54},[365,720,721,724],{"class":367,"line":454},[365,722,723],{"class":392},"@",[365,725,727],{"class":726},"sbsja","main\n",[365,729,730,733,736,738,741],{"class":367,"line":464},[365,731,732],{"class":726},"struct",[365,734,735],{"class":580}," MyApp",[365,737,377],{"class":408},[365,739,740],{"class":580}," App ",[365,742,743],{"class":408},"{\n",[365,745,746,749,752,755,758,760,762,764,767,769,771,773,775,777,779,781],{"class":367,"line":475},[365,747,748],{"class":392},"    @",[365,750,751],{"class":726},"State",[365,753,754],{"class":602}," private",[365,756,757],{"class":602}," var",[365,759,606],{"class":388},[365,761,609],{"class":392},[365,763,612],{"class":576},[365,765,766],{"class":392},"?",[365,768,615],{"class":404},[365,770,409],{"class":408},[365,772,620],{"class":404},[365,774,377],{"class":408},[365,776,418],{"class":417},[365,778,627],{"class":421},[365,780,424],{"class":417},[365,782,632],{"class":408},[365,784,785],{"class":367,"line":492},[365,786,586],{"emptyLinePlaceholder":54},[365,788,789,792,795,798,801],{"class":367,"line":537},[365,790,791],{"class":602},"    var",[365,793,794],{"class":388}," body: ",[365,796,797],{"class":602},"some",[365,799,800],{"class":388}," Scene ",[365,802,743],{"class":408},[365,804,805,808],{"class":367,"line":545},[365,806,807],{"class":404},"        WindowGroup",[365,809,810],{"class":408}," {\n",[365,812,814,817],{"class":367,"line":813},10,[365,815,816],{"class":404},"            ContentView",[365,818,660],{"class":408},[365,820,822,825,828,830,833],{"class":367,"line":821},11,[365,823,824],{"class":388},"                .",[365,826,827],{"class":404},"environment",[365,829,409],{"class":408},[365,831,832],{"class":388},"\\.configDirectorClient, client",[365,834,632],{"class":408},[365,836,838,840,843],{"class":367,"line":837},12,[365,839,824],{"class":388},[365,841,842],{"class":404},"task",[365,844,810],{"class":408},[365,846,848,851,854,856,859,861,863,866,868,871,873,876,878,880,883,885],{"class":367,"line":847},13,[365,849,850],{"class":576},"                    await",[365,852,853],{"class":388}," client",[365,855,766],{"class":392},[365,857,858],{"class":388},".",[365,860,657],{"class":404},[365,862,409],{"class":408},[365,864,865],{"class":404},"context",[365,867,377],{"class":408},[365,869,870],{"class":404}," ConfigDirectorContext",[365,872,409],{"class":408},[365,874,875],{"class":404},"id",[365,877,377],{"class":408},[365,879,418],{"class":417},[365,881,882],{"class":421},"user-123",[365,884,424],{"class":417},[365,886,887],{"class":408},"))\n",[365,889,891],{"class":367,"line":890},14,[365,892,893],{"class":408},"                }\n",[365,895,897],{"class":367,"line":896},15,[365,898,899],{"class":408},"        }\n",[365,901,903],{"class":367,"line":902},16,[365,904,905],{"class":408},"    }\n",[365,907,909],{"class":367,"line":908},17,[365,910,911],{"class":408},"}\n",[365,913,915],{"class":367,"line":914},18,[365,916,586],{"emptyLinePlaceholder":54},[365,918,920,923,926],{"class":367,"line":919},19,[365,921,922],{"class":726},"extension",[365,924,925],{"class":580}," EnvironmentValues",[365,927,810],{"class":408},[365,929,931,933,936,938,941],{"class":367,"line":930},20,[365,932,748],{"class":392},[365,934,935],{"class":726},"Entry",[365,937,757],{"class":602},[365,939,940],{"class":388}," configDirectorClient: ConfigDirectorClient",[365,942,943],{"class":392},"?\n",[365,945,947],{"class":367,"line":946},21,[365,948,911],{"class":408},[665,950,951,952,958],{},"The SDK follows the app lifecycle so it can release its network connection while the app is backgrounded. See ",[341,953,955],{"href":954},"#connection",[322,956,957],{},"connection"," below to manage that yourself instead.",[960,961,963],"h3",{"id":962},"additional-configuration-options","Additional configuration options",[264,965,966,967,858],{},"These options can be passed in to ",[322,968,969],{},"ConfigDirectorClientOptions",[971,972,974],"h4",{"id":973},"metadata",[322,975,973],{},[264,977,978,979,981],{},"The ",[322,980,973],{}," option allows you to provide your application's name and version. These values can be used in targeting rules conditionals. For example, if a certain feature should only be enabled starting with a certain version of your application.",[264,983,984,985,988,989,992,993,996],{},"Whichever of the two you leave unset is read from the running application's bundle — ",[322,986,987],{},"CFBundleDisplayName"," (falling back to ",[322,990,991],{},"CFBundleName",") for the name, and ",[322,994,995],{},"CFBundleShortVersionString"," for the version — so most applications do not need to set either one.",[356,998,1000],{"className":380,"code":999,"filename":569,"language":253,"meta":361,"style":361},"let client = try ConfigDirectorClient(\n    clientSDKKey: \"YOUR-CLIENT-SDK-KEY\",\n    options: ConfigDirectorClientOptions(\n        metadata: ConfigDirectorMetaContext(\n            appName: \"YOUR-APP-NAME\",\n            appVersion: \"1.0.2\"\n        )\n    )\n)\n",[322,1001,1002,1016,1031,1043,1055,1071,1086,1091,1096],{"__ignoreMap":361},[365,1003,1004,1006,1008,1010,1012,1014],{"class":367,"line":368},[365,1005,603],{"class":602},[365,1007,606],{"class":388},[365,1009,609],{"class":392},[365,1011,612],{"class":576},[365,1013,615],{"class":404},[365,1015,472],{"class":408},[365,1017,1018,1021,1023,1025,1027,1029],{"class":367,"line":398},[365,1019,1020],{"class":404},"    clientSDKKey",[365,1022,377],{"class":408},[365,1024,418],{"class":417},[365,1026,627],{"class":421},[365,1028,424],{"class":417},[365,1030,445],{"class":388},[365,1032,1033,1036,1038,1041],{"class":367,"line":448},[365,1034,1035],{"class":404},"    options",[365,1037,377],{"class":408},[365,1039,1040],{"class":404}," ConfigDirectorClientOptions",[365,1042,472],{"class":408},[365,1044,1045,1048,1050,1053],{"class":367,"line":454},[365,1046,1047],{"class":404},"        metadata",[365,1049,377],{"class":408},[365,1051,1052],{"class":404}," ConfigDirectorMetaContext",[365,1054,472],{"class":408},[365,1056,1057,1060,1062,1064,1067,1069],{"class":367,"line":464},[365,1058,1059],{"class":404},"            appName",[365,1061,377],{"class":408},[365,1063,418],{"class":417},[365,1065,1066],{"class":421},"YOUR-APP-NAME",[365,1068,424],{"class":417},[365,1070,445],{"class":388},[365,1072,1073,1076,1078,1080,1083],{"class":367,"line":475},[365,1074,1075],{"class":404},"            appVersion",[365,1077,377],{"class":408},[365,1079,418],{"class":417},[365,1081,1082],{"class":421},"1.0.2",[365,1084,1085],{"class":417},"\"\n",[365,1087,1088],{"class":367,"line":492},[365,1089,1090],{"class":408},"        )\n",[365,1092,1093],{"class":367,"line":537},[365,1094,1095],{"class":408},"    )\n",[365,1097,1098],{"class":367,"line":545},[365,1099,632],{"class":408},[971,1101,1103],{"id":1102},"logger",[322,1104,1102],{},[264,1106,1107,1108,1111,1112,1114,1115,1118],{},"By default, the SDK logs to the unified logging system under the ",[322,1109,1110],{},"com.configdirector.sdk"," subsystem, and it is set to log warnings and errors only. You can configure a ",[322,1113,1102],{}," by either creating a ConfigDirector console logger with a different log level, or by conforming to the ",[322,1116,1117],{},"ConfigDirectorLogger"," protocol to provide your own logger. The protocol can be used to create an adapter to another logging library.",[264,1120,1121],{},"Configure the ConfigDirector console logger to a different level:",[356,1123,1125],{"className":380,"code":1124,"filename":569,"language":253,"meta":361,"style":361},"let client = try ConfigDirectorClient(\n    clientSDKKey: \"YOUR-CLIENT-SDK-KEY\",\n    options: ConfigDirectorClientOptions(logger: ConsoleLogger(level: .debug))\n)\n",[322,1126,1127,1141,1155,1184],{"__ignoreMap":361},[365,1128,1129,1131,1133,1135,1137,1139],{"class":367,"line":368},[365,1130,603],{"class":602},[365,1132,606],{"class":388},[365,1134,609],{"class":392},[365,1136,612],{"class":576},[365,1138,615],{"class":404},[365,1140,472],{"class":408},[365,1142,1143,1145,1147,1149,1151,1153],{"class":367,"line":398},[365,1144,1020],{"class":404},[365,1146,377],{"class":408},[365,1148,418],{"class":417},[365,1150,627],{"class":421},[365,1152,424],{"class":417},[365,1154,445],{"class":388},[365,1156,1157,1159,1161,1163,1165,1167,1169,1172,1174,1177,1179,1182],{"class":367,"line":448},[365,1158,1035],{"class":404},[365,1160,377],{"class":408},[365,1162,1040],{"class":404},[365,1164,409],{"class":408},[365,1166,1102],{"class":404},[365,1168,377],{"class":408},[365,1170,1171],{"class":404}," ConsoleLogger",[365,1173,409],{"class":408},[365,1175,1176],{"class":404},"level",[365,1178,377],{"class":408},[365,1180,1181],{"class":388}," .debug",[365,1183,887],{"class":408},[365,1185,1186],{"class":367,"line":454},[365,1187,632],{"class":408},[264,1189,1190,1191,427,1194,427,1197,1200,1201,1204,1205,858],{},"The available levels are ",[322,1192,1193],{},".off",[322,1195,1196],{},".error",[322,1198,1199],{},".warn"," (the default), ",[322,1202,1203],{},".info"," and ",[322,1206,1207],{},".debug",[264,1209,1210],{},"Implement your own logger adapter:",[356,1212,1215],{"className":380,"code":1213,"filename":1214,"language":253,"meta":361,"style":361},"import ConfigDirector\n\nstruct MyLogger: ConfigDirectorLogger {\n    \u002F\u002F Messages more verbose than this level are never passed to `log`.\n    let level: ConfigDirectorLogLevel = .info\n\n    func log(_ level: ConfigDirectorLogLevel, message: String, error: (any Error)?) {\n        \u002F\u002F your specific logging library implementation here\n    }\n}\n\nlet client = try ConfigDirectorClient(\n    clientSDKKey: \"YOUR-CLIENT-SDK-KEY\",\n    options: ConfigDirectorClientOptions(logger: MyLogger())\n)\n","MyLogger.swift",[322,1216,1217,1223,1227,1241,1246,1259,1263,1318,1323,1327,1331,1335,1349,1363,1382],{"__ignoreMap":361},[365,1218,1219,1221],{"class":367,"line":368},[365,1220,577],{"class":576},[365,1222,581],{"class":580},[365,1224,1225],{"class":367,"line":398},[365,1226,586],{"emptyLinePlaceholder":54},[365,1228,1229,1231,1234,1236,1239],{"class":367,"line":448},[365,1230,732],{"class":726},[365,1232,1233],{"class":580}," MyLogger",[365,1235,377],{"class":408},[365,1237,1238],{"class":580}," ConfigDirectorLogger ",[365,1240,743],{"class":408},[365,1242,1243],{"class":367,"line":454},[365,1244,1245],{"class":591},"    \u002F\u002F Messages more verbose than this level are never passed to `log`.\n",[365,1247,1248,1251,1254,1256],{"class":367,"line":464},[365,1249,1250],{"class":602},"    let",[365,1252,1253],{"class":388}," level: ConfigDirectorLogLevel ",[365,1255,609],{"class":392},[365,1257,1258],{"class":388}," .info\n",[365,1260,1261],{"class":367,"line":475},[365,1262,586],{"emptyLinePlaceholder":54},[365,1264,1265,1268,1272,1274,1277,1281,1284,1288,1291,1295,1297,1300,1302,1304,1307,1310,1312,1314,1316],{"class":367,"line":492},[365,1266,1267],{"class":726},"    func",[365,1269,1271],{"class":1270},"sGLFI"," log",[365,1273,409],{"class":408},[365,1275,1276],{"class":1270},"_",[365,1278,1280],{"class":1279},"sFwrP"," level",[365,1282,1283],{"class":388},": ConfigDirectorLogLevel, ",[365,1285,1287],{"class":1286},"s95qv","message",[365,1289,1290],{"class":388},": ",[365,1292,1294],{"class":1293},"sZMiF","String",[365,1296,427],{"class":388},[365,1298,1299],{"class":1286},"error",[365,1301,1290],{"class":388},[365,1303,409],{"class":408},[365,1305,1306],{"class":602},"any",[365,1308,1309],{"class":1293}," Error",[365,1311,442],{"class":408},[365,1313,766],{"class":392},[365,1315,442],{"class":408},[365,1317,810],{"class":408},[365,1319,1320],{"class":367,"line":537},[365,1321,1322],{"class":591},"        \u002F\u002F your specific logging library implementation here\n",[365,1324,1325],{"class":367,"line":545},[365,1326,905],{"class":408},[365,1328,1329],{"class":367,"line":813},[365,1330,911],{"class":408},[365,1332,1333],{"class":367,"line":821},[365,1334,586],{"emptyLinePlaceholder":54},[365,1336,1337,1339,1341,1343,1345,1347],{"class":367,"line":837},[365,1338,603],{"class":602},[365,1340,606],{"class":388},[365,1342,609],{"class":392},[365,1344,612],{"class":576},[365,1346,615],{"class":404},[365,1348,472],{"class":408},[365,1350,1351,1353,1355,1357,1359,1361],{"class":367,"line":847},[365,1352,1020],{"class":404},[365,1354,377],{"class":408},[365,1356,418],{"class":417},[365,1358,627],{"class":421},[365,1360,424],{"class":417},[365,1362,445],{"class":388},[365,1364,1365,1367,1369,1371,1373,1375,1377,1379],{"class":367,"line":890},[365,1366,1035],{"class":404},[365,1368,377],{"class":408},[365,1370,1040],{"class":404},[365,1372,409],{"class":408},[365,1374,1102],{"class":404},[365,1376,377],{"class":408},[365,1378,1233],{"class":404},[365,1380,1381],{"class":408},"())\n",[365,1383,1384],{"class":367,"line":896},[365,1385,632],{"class":408},[971,1387,1388],{"id":957},[322,1389,957],{},[264,1391,1392,1395],{},[322,1393,1394],{},"ConnectionOptions"," accepts five optional values:",[1397,1398,1399,1433,1459,1486,1514],"ul",{},[556,1400,1401,1404],{},[322,1402,1403],{},"mode",[1397,1405,1406,1423,1428],{},[556,1407,1408,1409,1412,1413,1416,1417,1419,1420,1422],{},"The connection mode, which can be ",[322,1410,1411],{},".streaming"," or ",[322,1414,1415],{},".polling",". It is recommended to use the default of ",[322,1418,1411],{}," unless you have a specific need to use ",[322,1421,1415],{}," instead.",[556,1424,1425,1427],{},[322,1426,1411],{}," holds a connection open and receives changes as they happen, reconnecting on its own with a backoff.",[556,1429,1430,1431],{},"Defaults to ",[322,1432,1411],{},[556,1434,1435,1438],{},[322,1436,1437],{},"pollingInterval",[1397,1439,1440,1453],{},[556,1441,1442,1443,1445,1446,1448,1449,858],{},"How often to re-fetch config state, in seconds, when ",[322,1444,1403],{}," is ",[322,1447,1415],{},". It has no effect in any other mode. A value below the minimum of 30 seconds is raised to 30 seconds and a warning is logged. See ",[341,1450,1452],{"href":1451},"\u002Fgetting-started\u002Farchitecture#polling-intervals","Polling intervals",[556,1454,1430,1455,1458],{},[322,1456,1457],{},"60"," seconds",[556,1460,1461,1464],{},[322,1462,1463],{},"timeout",[1397,1465,1466,1475,1481],{},[556,1467,1468,1469,1471,1472,1474],{},"The timeout to be used in initialization and when updating the context. This is how long ",[322,1470,657],{}," will wait for data from ConfigDirector services before returning. If the timeout is reached, ",[322,1473,657],{}," will return but the client will still be in an unready status and returning default values. The client will continue to attempt to connect and retrieve config values in the background.",[556,1476,1477,1478,1480],{},"If your application is used in environments where the users frequently have poor or no connection, you may want to use a lower timeout, or simply don't await the ",[322,1479,657],{}," call.",[556,1482,1430,1483,1458],{},[322,1484,1485],{},"3",[556,1487,1488,1491],{},[322,1489,1490],{},"pausesWhileBackgrounded",[1397,1492,1493,1506,1509],{},[556,1494,1495,1496,1499,1500,1204,1503,858],{},"Whether to pause the connection while the app is in the background and resume it when the app returns to the foreground. Mobile operating systems terminate background connections on their own, so this is enabled by default. Set it to ",[322,1497,1498],{},"false"," to manage the connection yourself with ",[322,1501,1502],{},"pauseNetwork()",[322,1504,1505],{},"resumeNetwork()",[556,1507,1508],{},"It has no effect on macOS, where an app keeps running, and keeps its connections, once it leaves the foreground.",[556,1510,1430,1511],{},[322,1512,1513],{},"true",[556,1515,1516,1519],{},[322,1517,1518],{},"baseURL",[1397,1520,1521,1524],{},[556,1522,1523],{},"The base URL used to connect to ConfigDirector services.",[556,1525,1526],{},"This should only be provided if your environment requires you to configure a proxy server in order to connect to ConfigDirector services.",[356,1528,1530],{"className":380,"code":1529,"filename":569,"language":253,"meta":361,"style":361},"let client = try ConfigDirectorClient(\n    clientSDKKey: \"YOUR-CLIENT-SDK-KEY\",\n    options: ConfigDirectorClientOptions(\n        connection: ConnectionOptions(mode: .polling, pollingInterval: 600, timeout: 2)\n    )\n)\n",[322,1531,1532,1546,1560,1570,1608,1612],{"__ignoreMap":361},[365,1533,1534,1536,1538,1540,1542,1544],{"class":367,"line":368},[365,1535,603],{"class":602},[365,1537,606],{"class":388},[365,1539,609],{"class":392},[365,1541,612],{"class":576},[365,1543,615],{"class":404},[365,1545,472],{"class":408},[365,1547,1548,1550,1552,1554,1556,1558],{"class":367,"line":398},[365,1549,1020],{"class":404},[365,1551,377],{"class":408},[365,1553,418],{"class":417},[365,1555,627],{"class":421},[365,1557,424],{"class":417},[365,1559,445],{"class":388},[365,1561,1562,1564,1566,1568],{"class":367,"line":448},[365,1563,1035],{"class":404},[365,1565,377],{"class":408},[365,1567,1040],{"class":404},[365,1569,472],{"class":408},[365,1571,1572,1575,1577,1580,1582,1584,1586,1589,1591,1593,1597,1599,1601,1603,1606],{"class":367,"line":454},[365,1573,1574],{"class":404},"        connection",[365,1576,377],{"class":408},[365,1578,1579],{"class":404}," ConnectionOptions",[365,1581,409],{"class":408},[365,1583,1403],{"class":404},[365,1585,377],{"class":408},[365,1587,1588],{"class":388}," .polling, ",[365,1590,1437],{"class":404},[365,1592,377],{"class":408},[365,1594,1596],{"class":1595},"srdBf"," 600",[365,1598,427],{"class":388},[365,1600,1463],{"class":404},[365,1602,377],{"class":408},[365,1604,1605],{"class":1595}," 2",[365,1607,632],{"class":408},[365,1609,1610],{"class":367,"line":464},[365,1611,1095],{"class":408},[365,1613,1614],{"class":367,"line":475},[365,1615,632],{"class":408},[960,1617,1619],{"id":1618},"events","Events",[264,1621,1622,1623,1625,1626,1629,1630,1633,1634,1637],{},"Events notify you of some key actions from the client. ",[322,1624,1618],{}," publishes the client's lifecycle changes, and ",[322,1627,1628],{},"evaluations"," publishes every individual config evaluation. Each is an ",[322,1631,1632],{},"AsyncStream"," you consume with a ",[322,1635,1636],{},"for await"," loop, and each access to the property returns an independent stream, so several parts of your app can observe them at once. Cancelling the consuming task ends the loop, and every stream is finished when the client is closed.",[356,1639,1641],{"className":380,"code":1640,"filename":569,"language":253,"meta":361,"style":361},"for await event in client.events {\n    switch event {\n    case let .ready(reason):\n        print(\"Client is ready after \\(reason)\")\n    case let .configsUpdated(update):\n        print(\"Configs updated: \\(update.keys), removed: \\(update.removedKeys)\")\n    case let .contextUpdated(context):\n        print(\"Context updated: \\(context?.id ?? \"none\")\")\n    }\n}\n",[322,1642,1643,1662,1671,1695,1719,1739,1777,1796,1833,1837],{"__ignoreMap":361},[365,1644,1645,1648,1651,1654,1657,1660],{"class":367,"line":368},[365,1646,1647],{"class":576},"for",[365,1649,1650],{"class":576}," await",[365,1652,1653],{"class":388}," event ",[365,1655,1656],{"class":576},"in",[365,1658,1659],{"class":388}," client.events ",[365,1661,743],{"class":408},[365,1663,1664,1667,1669],{"class":367,"line":398},[365,1665,1666],{"class":576},"    switch",[365,1668,1653],{"class":388},[365,1670,743],{"class":408},[365,1672,1673,1676,1679,1682,1685,1687,1690,1692],{"class":367,"line":448},[365,1674,1675],{"class":576},"    case",[365,1677,1678],{"class":602}," let",[365,1680,1681],{"class":388}," .",[365,1683,1684],{"class":404},"ready",[365,1686,409],{"class":408},[365,1688,1689],{"class":388},"reason",[365,1691,442],{"class":408},[365,1693,1694],{"class":392},":\n",[365,1696,1697,1700,1702,1704,1707,1710,1713,1715,1717],{"class":367,"line":454},[365,1698,1699],{"class":404},"        print",[365,1701,409],{"class":408},[365,1703,424],{"class":417},[365,1705,1706],{"class":421},"Client is ready after ",[365,1708,1709],{"class":417},"\\(",[365,1711,1689],{"class":1712},"sfo-9",[365,1714,442],{"class":417},[365,1716,424],{"class":417},[365,1718,632],{"class":408},[365,1720,1721,1723,1725,1727,1730,1732,1735,1737],{"class":367,"line":464},[365,1722,1675],{"class":576},[365,1724,1678],{"class":602},[365,1726,1681],{"class":388},[365,1728,1729],{"class":404},"configsUpdated",[365,1731,409],{"class":408},[365,1733,1734],{"class":388},"update",[365,1736,442],{"class":408},[365,1738,1694],{"class":392},[365,1740,1741,1743,1745,1747,1750,1752,1755,1759,1761,1764,1766,1768,1771,1773,1775],{"class":367,"line":475},[365,1742,1699],{"class":404},[365,1744,409],{"class":408},[365,1746,424],{"class":417},[365,1748,1749],{"class":421},"Configs updated: ",[365,1751,1709],{"class":417},[365,1753,1754],{"class":1712},"update.",[365,1756,1758],{"class":1757},"s_hVV","keys",[365,1760,442],{"class":417},[365,1762,1763],{"class":421},", removed: ",[365,1765,1709],{"class":417},[365,1767,1754],{"class":1712},[365,1769,1770],{"class":388},"removedKeys",[365,1772,442],{"class":417},[365,1774,424],{"class":417},[365,1776,632],{"class":408},[365,1778,1779,1781,1783,1785,1788,1790,1792,1794],{"class":367,"line":492},[365,1780,1675],{"class":576},[365,1782,1678],{"class":602},[365,1784,1681],{"class":388},[365,1786,1787],{"class":404},"contextUpdated",[365,1789,409],{"class":408},[365,1791,865],{"class":388},[365,1793,442],{"class":408},[365,1795,1694],{"class":392},[365,1797,1798,1800,1802,1804,1807,1809,1811,1813,1815,1817,1820,1822,1825,1827,1829,1831],{"class":367,"line":537},[365,1799,1699],{"class":404},[365,1801,409],{"class":408},[365,1803,424],{"class":417},[365,1805,1806],{"class":421},"Context updated: ",[365,1808,1709],{"class":417},[365,1810,865],{"class":1712},[365,1812,766],{"class":392},[365,1814,858],{"class":1712},[365,1816,875],{"class":388},[365,1818,1819],{"class":392}," ??",[365,1821,418],{"class":417},[365,1823,1824],{"class":421},"none",[365,1826,424],{"class":417},[365,1828,442],{"class":417},[365,1830,424],{"class":417},[365,1832,632],{"class":408},[365,1834,1835],{"class":367,"line":545},[365,1836,905],{"class":408},[365,1838,1839],{"class":367,"line":813},[365,1840,911],{"class":408},[264,1842,1843,1844,377],{},"The following events are published on ",[322,1845,1846],{},"client.events",[1397,1848,1849,1878,1905],{},[556,1850,1851,1856],{},[322,1852,1855],{"className":1853},[1854],"font-semibold","ready(ConnectReason)",[1397,1857,1858,1861],{},[556,1859,1860],{},"Emitted when the client is initialized, or after reconnection due to a context update or a resumed network connection. When this event is emitted it means the client has received a payload from the ConfigDirector servers and is ready to evaluate configs.",[556,1862,1863,1864,1867,1868,427,1871,1874,1875,858],{},"The associated ",[322,1865,1866],{},"ConnectReason"," is the action that triggered the client to connect\u002Freconnect, which can be ",[322,1869,1870],{},".initialization",[322,1872,1873],{},".contextUpdate",", or ",[322,1876,1877],{},".networkResume",[556,1879,1880,1884],{},[322,1881,1883],{"className":1882},[1854],"configsUpdated(ConfigsUpdate)",[1397,1885,1886,1889,1898],{},[556,1887,1888],{},"Emitted when a payload is received from the ConfigDirector servers with config data. It is emitted during initialization or context update when an entire config payload is received. After initialization or context update, it is emitted when updates are pushed from the server (or discovered via polling if that connection mode is used).",[556,1890,1891,1893,1894,1897],{},[322,1892,1758],{}," - A ",[322,1895,1896],{},"[String]"," listing the config keys that were included in the payload from the server. On a delta update, these are only the configs that changed.",[556,1899,1900,1893,1902,1904],{},[322,1901,1770],{},[322,1903,1896],{}," listing the keys of configs the payload removed. A config is removed when a full payload no longer includes it. Empty when nothing was removed, and always empty on a delta update.",[556,1906,1907,1911],{},[322,1908,1910],{"className":1909},[1854],"contextUpdated(ConfigDirectorContext?)",[1397,1912,1913,1919],{},[556,1914,1915,1916,1918],{},"Emitted whenever the user context takes effect, including during initialization. It is emitted before ",[322,1917,1684],{},", therefore should not be relied upon as a lifecycle event but rather as an informational event to track updates to the user context.",[556,1920,1921,1922,858],{},"The associated value is the context the client is now evaluating against. It can be ",[322,1923,1924],{},"nil",[264,1926,1927,1930,1931,1934,1935,1938,1939,1942,1943,1945],{},[322,1928,1929],{},"client.evaluations"," publishes a ",[322,1932,1933],{},"ConfigEvaluation"," every time a config is evaluated, which can be useful for debugging what a screen actually read, and for capturing additional context for analytics events. This includes calls to ",[322,1936,1937],{},"value(for:default:)"," and evaluations delivered by a ",[322,1940,1941],{},"values(for:default:)"," stream. A ",[322,1944,1933],{}," carries:",[1397,1947,1948,1954,1976,1989,1995,2001],{},[556,1949,1950,1953],{},[322,1951,1952],{},"key: String"," - The config key that was evaluated.",[556,1955,1956,1959,1960,1412,1962,1964,1965,1968,1969,1971,1972,1975],{},[322,1957,1958],{},"value: ConfigEvaluationValue"," - The value the config evaluated to. It can be the default value provided to ",[322,1961,1937],{},[322,1963,1941],{},", for example if the config was evaluated before the client was initialized. Read it back as the type the config was evaluated as with ",[322,1966,1967],{},"evaluation.value.as(Bool.self)",", which returns ",[322,1970,1924],{}," when the config was evaluated as some other type. Its ",[322,1973,1974],{},"description"," is a textual form of the value, suitable for logging.",[556,1977,1978,1981,1982,1985,1986,1988],{},[322,1979,1980],{},"valueID: String?"," - The value ID, which is a stable hash of the value that can be used for analytics or other third parties rather than sending the ",[322,1983,1984],{},"value",". This can be useful for large values, like a JSON config, or to avoid disclosing the values themselves to third parties. It is ",[322,1987,1924],{}," if the evaluation had to fall back to the default value.",[556,1990,1991,1994],{},[322,1992,1993],{},"isDefaultValue: Bool"," - Whether or not the evaluation fell back to the default value provided in code.",[556,1996,1997,2000],{},[322,1998,1999],{},"context: ConfigDirectorContext?"," - The context the config was evaluated against, if one was set.",[556,2002,2003,2006,2007,2010,2011,2013,2014],{},[322,2004,2005],{},"reason: EvaluationReason"," - The reason for the evaluation resolution. In the case the config successfully evaluated based on server-provided targeting rules, it will be ",[322,2008,2009],{},".foundMatch",". If the evaluation had to fall back to the default value, the ",[322,2012,1689],{}," will encode why the fallback was required:\n",[1397,2015,2016,2022,2028,2034,2040,2046,2052],{},[556,2017,2018,2021],{},[322,2019,2020],{},".clientNotReady"," - The evaluation happened before the client finished initialization.",[556,2023,2024,2027],{},[322,2025,2026],{},".configStateMissing"," - The requested config key was not present in the payload received from the server. This could be due to an incorrect config key, or a config that was not enabled to be available to client SDKs.",[556,2029,2030,2033],{},[322,2031,2032],{},".valueMissing"," - The config had no value for the current context.",[556,2035,2036,2039],{},[322,2037,2038],{},".invalidNumber"," - The config was requested as a number but the value received from the server could not be converted to a number.",[556,2041,2042,2045],{},[322,2043,2044],{},".invalidBoolean"," - The config was requested as a boolean but the value received from the server could not be converted to a boolean.",[556,2047,2048,2051],{},[322,2049,2050],{},".invalidJSON"," - The config was requested as JSON but the value received from the server could not be decoded into the requested type.",[556,2053,2054,2057],{},[322,2055,2056],{},".typeMismatch"," - The config was requested with a data type that did not match the type of the config and no reasonable type conversion was possible.",[264,2059,2060,1445,2062,2065],{},[322,2061,1933],{},[322,2063,2064],{},"Equatable",", so evaluations can be compared or de-duplicated before they are forwarded on.",[356,2067,2069],{"className":380,"code":2068,"filename":569,"language":253,"meta":361,"style":361},"for await evaluation in client.evaluations where evaluation.isDefaultValue {\n    print(\"'\\(evaluation.key)' fell back to its default: \\(evaluation.reason.rawValue)\")\n}\n",[322,2070,2071,2093,2135],{"__ignoreMap":361},[365,2072,2073,2075,2077,2080,2082,2085,2088,2091],{"class":367,"line":368},[365,2074,1647],{"class":576},[365,2076,1650],{"class":576},[365,2078,2079],{"class":388}," evaluation ",[365,2081,1656],{"class":576},[365,2083,2084],{"class":388}," client.evaluations ",[365,2086,2087],{"class":576},"where",[365,2089,2090],{"class":388}," evaluation.isDefaultValue ",[365,2092,743],{"class":408},[365,2094,2095,2098,2100,2102,2105,2107,2110,2113,2115,2118,2120,2122,2124,2126,2129,2131,2133],{"class":367,"line":398},[365,2096,2097],{"class":404},"    print",[365,2099,409],{"class":408},[365,2101,424],{"class":417},[365,2103,2104],{"class":421},"'",[365,2106,1709],{"class":417},[365,2108,2109],{"class":1712},"evaluation.",[365,2111,2112],{"class":388},"key",[365,2114,442],{"class":417},[365,2116,2117],{"class":421},"' fell back to its default: ",[365,2119,1709],{"class":417},[365,2121,2109],{"class":1712},[365,2123,1689],{"class":388},[365,2125,858],{"class":1712},[365,2127,2128],{"class":1757},"rawValue",[365,2130,442],{"class":417},[365,2132,424],{"class":417},[365,2134,632],{"class":408},[365,2136,2137],{"class":367,"line":448},[365,2138,911],{"class":408},[356,2140,2142],{"className":380,"code":2141,"filename":569,"language":253,"meta":361,"style":361},"for await evaluation in client.evaluations {\n    guard let isOn = evaluation.value.as(Bool.self) else { continue }\n\n    print(\"'\\(evaluation.key)' evaluated to \\(isOn), value ID \\(evaluation.valueID ?? \"none\")\")\n}\n",[322,2143,2144,2158,2204,2208,2260],{"__ignoreMap":361},[365,2145,2146,2148,2150,2152,2154,2156],{"class":367,"line":368},[365,2147,1647],{"class":576},[365,2149,1650],{"class":576},[365,2151,2079],{"class":388},[365,2153,1656],{"class":576},[365,2155,2084],{"class":388},[365,2157,743],{"class":408},[365,2159,2160,2163,2165,2168,2170,2173,2175,2177,2180,2182,2185,2187,2190,2192,2195,2198,2201],{"class":367,"line":398},[365,2161,2162],{"class":576},"    guard",[365,2164,1678],{"class":602},[365,2166,2167],{"class":388}," isOn ",[365,2169,609],{"class":392},[365,2171,2172],{"class":388}," evaluation.",[365,2174,1984],{"class":1757},[365,2176,858],{"class":388},[365,2178,2179],{"class":392},"as",[365,2181,409],{"class":408},[365,2183,2184],{"class":1293},"Bool",[365,2186,858],{"class":388},[365,2188,2189],{"class":602},"self",[365,2191,442],{"class":408},[365,2193,2194],{"class":576}," else",[365,2196,2197],{"class":408}," {",[365,2199,2200],{"class":576}," continue",[365,2202,2203],{"class":408}," }\n",[365,2205,2206],{"class":367,"line":448},[365,2207,586],{"emptyLinePlaceholder":54},[365,2209,2210,2212,2214,2216,2218,2220,2222,2224,2226,2229,2231,2234,2236,2239,2241,2243,2246,2248,2250,2252,2254,2256,2258],{"class":367,"line":454},[365,2211,2097],{"class":404},[365,2213,409],{"class":408},[365,2215,424],{"class":417},[365,2217,2104],{"class":421},[365,2219,1709],{"class":417},[365,2221,2109],{"class":1712},[365,2223,2112],{"class":388},[365,2225,442],{"class":417},[365,2227,2228],{"class":421},"' evaluated to ",[365,2230,1709],{"class":417},[365,2232,2233],{"class":1712},"isOn",[365,2235,442],{"class":417},[365,2237,2238],{"class":421},", value ID ",[365,2240,1709],{"class":417},[365,2242,2109],{"class":1712},[365,2244,2245],{"class":388},"valueID",[365,2247,1819],{"class":392},[365,2249,418],{"class":417},[365,2251,1824],{"class":421},[365,2253,424],{"class":417},[365,2255,442],{"class":417},[365,2257,424],{"class":417},[365,2259,632],{"class":408},[365,2261,2262],{"class":367,"line":464},[365,2263,911],{"class":408},[2265,2266,2267,2268,2270],"warning",{},"Do not update view state straight from the ",[322,2269,1628],{}," stream. The state change re-renders the view, which reads the config again, which publishes another evaluation.",[259,2272,2274],{"id":2273},"retrieve-config-values","Retrieve config values",[264,2276,2277,2278,2280],{},"To synchronously retrieve config values, use the client's ",[322,2279,1937],{}," method. It requires two arguments. The first argument is the config key, and the second is the default value to be returned if the client has not yet received config values from ConfigDirector services.",[264,2282,2283,2284,2286,2287,2289,2290,2292],{},"You can also subscribe to config value changes via the ",[322,2285,1941],{}," method. It takes the same two arguments and returns an ",[322,2288,1632],{}," that emits the config's current value on subscription and then every time the evaluated value changes, whether because it was edited in the ConfigDirector dashboard or because the context was updated. Consecutive identical values are not re-emitted. When a full payload no longer includes the watched config, the stream emits the default value, as ",[322,2291,1937],{}," would now return it. Cancelling the task consuming the stream stops watching.",[356,2294,2297],{"className":380,"code":2295,"filename":2296,"language":253,"meta":361,"style":361},"\u002F\u002F Retrieve the current value. The default value decides the type the config\n\u002F\u002F is read as, and is returned until the client is ready.\nlet darkMode = client.value(for: \"my-config-key\", default: false)\n\n\u002F\u002F Subscribe to value updates. The stream yields the current value right away\n\u002F\u002F and then every time the evaluated value changes.\nfor await darkMode in client.values(for: \"my-config-key\", default: false) {\n    print(\"Value updated: \\(darkMode)\")\n}\n","ContentView.swift",[322,2298,2299,2304,2309,2348,2352,2357,2362,2401,2423],{"__ignoreMap":361},[365,2300,2301],{"class":367,"line":368},[365,2302,2303],{"class":591},"\u002F\u002F Retrieve the current value. The default value decides the type the config\n",[365,2305,2306],{"class":367,"line":398},[365,2307,2308],{"class":591},"\u002F\u002F is read as, and is returned until the client is ready.\n",[365,2310,2311,2313,2316,2318,2320,2322,2324,2326,2328,2330,2333,2335,2337,2340,2342,2346],{"class":367,"line":448},[365,2312,603],{"class":602},[365,2314,2315],{"class":388}," darkMode ",[365,2317,609],{"class":392},[365,2319,654],{"class":388},[365,2321,1984],{"class":1757},[365,2323,409],{"class":408},[365,2325,1647],{"class":404},[365,2327,377],{"class":408},[365,2329,418],{"class":417},[365,2331,2332],{"class":421},"my-config-key",[365,2334,424],{"class":417},[365,2336,427],{"class":388},[365,2338,2339],{"class":404},"default",[365,2341,377],{"class":408},[365,2343,2345],{"class":2344},"syTEX"," false",[365,2347,632],{"class":408},[365,2349,2350],{"class":367,"line":454},[365,2351,586],{"emptyLinePlaceholder":54},[365,2353,2354],{"class":367,"line":464},[365,2355,2356],{"class":591},"\u002F\u002F Subscribe to value updates. The stream yields the current value right away\n",[365,2358,2359],{"class":367,"line":475},[365,2360,2361],{"class":591},"\u002F\u002F and then every time the evaluated value changes.\n",[365,2363,2364,2366,2368,2370,2372,2374,2377,2379,2381,2383,2385,2387,2389,2391,2393,2395,2397,2399],{"class":367,"line":492},[365,2365,1647],{"class":576},[365,2367,1650],{"class":576},[365,2369,2315],{"class":388},[365,2371,1656],{"class":576},[365,2373,654],{"class":388},[365,2375,2376],{"class":1757},"values",[365,2378,409],{"class":408},[365,2380,1647],{"class":404},[365,2382,377],{"class":408},[365,2384,418],{"class":417},[365,2386,2332],{"class":421},[365,2388,424],{"class":417},[365,2390,427],{"class":388},[365,2392,2339],{"class":404},[365,2394,377],{"class":408},[365,2396,2345],{"class":2344},[365,2398,442],{"class":408},[365,2400,810],{"class":408},[365,2402,2403,2405,2407,2409,2412,2414,2417,2419,2421],{"class":367,"line":537},[365,2404,2097],{"class":404},[365,2406,409],{"class":408},[365,2408,424],{"class":417},[365,2410,2411],{"class":421},"Value updated: ",[365,2413,1709],{"class":417},[365,2415,2416],{"class":1712},"darkMode",[365,2418,442],{"class":417},[365,2420,424],{"class":417},[365,2422,632],{"class":408},[365,2424,2425],{"class":367,"line":545},[365,2426,911],{"class":408},[264,2428,2429,2430,427,2432,427,2434,1204,2437,2440],{},"Both methods infer their type from the default value. ",[322,2431,2184],{},[322,2433,1294],{},[322,2435,2436],{},"Int",[322,2438,2439],{},"Double"," are supported out of the box. If there is a type mismatch at runtime, the SDK will attempt to convert the served value to the requested type. If the conversion fails, it will return the default value rather than trapping. Mismatched types at runtime are captured by the telemetry collector and will surface as warnings in the ConfigDirector dashboard.",[356,2442,2444],{"className":380,"code":2443,"filename":2296,"language":253,"meta":361,"style":361},"client.value(for: \"my-string-config-key\", default: \"Default\")\n\nclient.value(for: \"my-integer-config-key\", default: 100)\n\nclient.value(for: \"my-boolean-config-key\", default: false)\n",[322,2445,2446,2481,2485,2515,2519],{"__ignoreMap":361},[365,2447,2448,2451,2453,2455,2457,2459,2461,2464,2466,2468,2470,2472,2474,2477,2479],{"class":367,"line":368},[365,2449,2450],{"class":388},"client.",[365,2452,1984],{"class":1757},[365,2454,409],{"class":408},[365,2456,1647],{"class":404},[365,2458,377],{"class":408},[365,2460,418],{"class":417},[365,2462,2463],{"class":421},"my-string-config-key",[365,2465,424],{"class":417},[365,2467,427],{"class":388},[365,2469,2339],{"class":404},[365,2471,377],{"class":408},[365,2473,418],{"class":417},[365,2475,2476],{"class":421},"Default",[365,2478,424],{"class":417},[365,2480,632],{"class":408},[365,2482,2483],{"class":367,"line":398},[365,2484,586],{"emptyLinePlaceholder":54},[365,2486,2487,2489,2491,2493,2495,2497,2499,2502,2504,2506,2508,2510,2513],{"class":367,"line":448},[365,2488,2450],{"class":388},[365,2490,1984],{"class":1757},[365,2492,409],{"class":408},[365,2494,1647],{"class":404},[365,2496,377],{"class":408},[365,2498,418],{"class":417},[365,2500,2501],{"class":421},"my-integer-config-key",[365,2503,424],{"class":417},[365,2505,427],{"class":388},[365,2507,2339],{"class":404},[365,2509,377],{"class":408},[365,2511,2512],{"class":1595}," 100",[365,2514,632],{"class":408},[365,2516,2517],{"class":367,"line":454},[365,2518,586],{"emptyLinePlaceholder":54},[365,2520,2521,2523,2525,2527,2529,2531,2533,2536,2538,2540,2542,2544,2546],{"class":367,"line":464},[365,2522,2450],{"class":388},[365,2524,1984],{"class":1757},[365,2526,409],{"class":408},[365,2528,1647],{"class":404},[365,2530,377],{"class":408},[365,2532,418],{"class":417},[365,2534,2535],{"class":421},"my-boolean-config-key",[365,2537,424],{"class":417},[365,2539,427],{"class":388},[365,2541,2339],{"class":404},[365,2543,377],{"class":408},[365,2545,2345],{"class":2344},[365,2547,632],{"class":408},[960,2549,2551],{"id":2550},"json-configs","JSON configs",[264,2553,2554,2555,2558,2559,2562],{},"A config holding a JSON document is read with ",[322,2556,2557],{},"value(for:as:default:)",", which decodes it into any ",[322,2560,2561],{},"Decodable"," type. It returns the default value when the config is not a JSON config, or when its document cannot be decoded into the type you asked for:",[356,2564,2566],{"className":380,"code":2565,"filename":2296,"language":253,"meta":361,"style":361},"struct Theme: Decodable {\n    let primary: String\n    let cornerRadius: Double\n}\n\nlet theme = client.value(\n    for: \"theme\",\n    as: Theme.self,\n    default: Theme(primary: \"#101010\", cornerRadius: 8)\n)\n",[322,2567,2568,2582,2592,2602,2606,2610,2625,2641,2655,2690],{"__ignoreMap":361},[365,2569,2570,2572,2575,2577,2580],{"class":367,"line":368},[365,2571,732],{"class":726},[365,2573,2574],{"class":580}," Theme",[365,2576,377],{"class":408},[365,2578,2579],{"class":580}," Decodable ",[365,2581,743],{"class":408},[365,2583,2584,2586,2589],{"class":367,"line":398},[365,2585,1250],{"class":602},[365,2587,2588],{"class":388}," primary: ",[365,2590,2591],{"class":1293},"String\n",[365,2593,2594,2596,2599],{"class":367,"line":448},[365,2595,1250],{"class":602},[365,2597,2598],{"class":388}," cornerRadius: ",[365,2600,2601],{"class":1293},"Double\n",[365,2603,2604],{"class":367,"line":454},[365,2605,911],{"class":408},[365,2607,2608],{"class":367,"line":464},[365,2609,586],{"emptyLinePlaceholder":54},[365,2611,2612,2614,2617,2619,2621,2623],{"class":367,"line":475},[365,2613,603],{"class":602},[365,2615,2616],{"class":388}," theme ",[365,2618,609],{"class":392},[365,2620,654],{"class":388},[365,2622,1984],{"class":1757},[365,2624,472],{"class":408},[365,2626,2627,2630,2632,2634,2637,2639],{"class":367,"line":492},[365,2628,2629],{"class":404},"    for",[365,2631,377],{"class":408},[365,2633,418],{"class":417},[365,2635,2636],{"class":421},"theme",[365,2638,424],{"class":417},[365,2640,445],{"class":388},[365,2642,2643,2646,2648,2651,2653],{"class":367,"line":537},[365,2644,2645],{"class":404},"    as",[365,2647,377],{"class":408},[365,2649,2650],{"class":388}," Theme.",[365,2652,2189],{"class":602},[365,2654,445],{"class":388},[365,2656,2657,2660,2662,2664,2666,2669,2671,2673,2676,2678,2680,2683,2685,2688],{"class":367,"line":545},[365,2658,2659],{"class":404},"    default",[365,2661,377],{"class":408},[365,2663,2574],{"class":404},[365,2665,409],{"class":408},[365,2667,2668],{"class":404},"primary",[365,2670,377],{"class":408},[365,2672,418],{"class":417},[365,2674,2675],{"class":421},"#101010",[365,2677,424],{"class":417},[365,2679,427],{"class":388},[365,2681,2682],{"class":404},"cornerRadius",[365,2684,377],{"class":408},[365,2686,2687],{"class":1595}," 8",[365,2689,632],{"class":408},[365,2691,2692],{"class":367,"line":813},[365,2693,632],{"class":408},[264,2695,2696,2699,2700,2702],{},[322,2697,2698],{},"values(for:as:default:)"," is the streaming counterpart. Its type has to be ",[322,2701,2064],{}," as well, since that is how the stream knows a decoded value did not change:",[356,2704,2706],{"className":380,"code":2705,"filename":2296,"language":253,"meta":361,"style":361},"for await theme in client.values(for: \"theme\", as: Theme.self, default: .fallback) {\n    self.theme = theme\n}\n",[322,2707,2708,2757,2770],{"__ignoreMap":361},[365,2709,2710,2712,2714,2716,2718,2720,2722,2724,2726,2728,2730,2732,2734,2736,2738,2740,2742,2744,2746,2748,2750,2753,2755],{"class":367,"line":368},[365,2711,1647],{"class":576},[365,2713,1650],{"class":576},[365,2715,2616],{"class":388},[365,2717,1656],{"class":576},[365,2719,654],{"class":388},[365,2721,2376],{"class":1757},[365,2723,409],{"class":408},[365,2725,1647],{"class":404},[365,2727,377],{"class":408},[365,2729,418],{"class":417},[365,2731,2636],{"class":421},[365,2733,424],{"class":417},[365,2735,427],{"class":388},[365,2737,2179],{"class":404},[365,2739,377],{"class":408},[365,2741,2650],{"class":388},[365,2743,2189],{"class":602},[365,2745,427],{"class":388},[365,2747,2339],{"class":404},[365,2749,377],{"class":408},[365,2751,2752],{"class":388}," .fallback",[365,2754,442],{"class":408},[365,2756,810],{"class":408},[365,2758,2759,2762,2765,2767],{"class":367,"line":398},[365,2760,2761],{"class":1757},"    self",[365,2763,2764],{"class":388},".theme ",[365,2766,609],{"class":392},[365,2768,2769],{"class":388}," theme\n",[365,2771,2772],{"class":367,"line":448},[365,2773,911],{"class":408},[960,2775,2777],{"id":2776},"custom-value-types","Custom value types",[264,2779,2780,2781,2784,2785,2788,2789,427,2792,1874,2795,2798,2799,2801],{},"To read a config as one of your own types, conform it to ",[322,2782,2783],{},"ConfigValue",". A config value arrives as the string the server served, and ",[322,2786,2787],{},"configValueKind"," decides which configs the type can be read from — ",[322,2790,2791],{},".boolean",[322,2793,2794],{},".string",[322,2796,2797],{},".number",". Returning ",[322,2800,1924],{}," from the initializer evaluates the config to the caller's default value:",[356,2803,2806],{"className":380,"code":2804,"filename":2805,"language":253,"meta":361,"style":361},"import ConfigDirector\n\nextension Locale: ConfigValue {\n    public static var configValueKind: ConfigValueKind { .string }\n\n    public init?(configValue: String) {\n        self.init(identifier: configValue)\n    }\n}\n\nlet locale = client.value(for: \"default-locale\", default: Locale(identifier: \"en_US\"))\n","Locale+ConfigValue.swift",[322,2807,2808,2814,2818,2832,2853,2857,2877,2899,2903,2907,2911],{"__ignoreMap":361},[365,2809,2810,2812],{"class":367,"line":368},[365,2811,577],{"class":576},[365,2813,581],{"class":580},[365,2815,2816],{"class":367,"line":398},[365,2817,586],{"emptyLinePlaceholder":54},[365,2819,2820,2822,2825,2827,2830],{"class":367,"line":448},[365,2821,922],{"class":726},[365,2823,2824],{"class":580}," Locale",[365,2826,377],{"class":408},[365,2828,2829],{"class":580}," ConfigValue ",[365,2831,743],{"class":408},[365,2833,2834,2837,2840,2842,2845,2848,2851],{"class":367,"line":454},[365,2835,2836],{"class":602},"    public",[365,2838,2839],{"class":726}," static",[365,2841,757],{"class":602},[365,2843,2844],{"class":388}," configValueKind: ConfigValueKind ",[365,2846,2847],{"class":408},"{",[365,2849,2850],{"class":388}," .string ",[365,2852,911],{"class":408},[365,2854,2855],{"class":367,"line":464},[365,2856,586],{"emptyLinePlaceholder":54},[365,2858,2859,2861,2864,2866,2869,2871,2873,2875],{"class":367,"line":475},[365,2860,2836],{"class":602},[365,2862,2863],{"class":726}," init?",[365,2865,409],{"class":408},[365,2867,2868],{"class":1286},"configValue",[365,2870,1290],{"class":388},[365,2872,1294],{"class":1293},[365,2874,442],{"class":408},[365,2876,810],{"class":408},[365,2878,2879,2882,2884,2887,2889,2892,2894,2897],{"class":367,"line":492},[365,2880,2881],{"class":1757},"        self",[365,2883,858],{"class":388},[365,2885,2886],{"class":726},"init",[365,2888,409],{"class":408},[365,2890,2891],{"class":404},"identifier",[365,2893,377],{"class":408},[365,2895,2896],{"class":388}," configValue",[365,2898,632],{"class":408},[365,2900,2901],{"class":367,"line":537},[365,2902,905],{"class":408},[365,2904,2905],{"class":367,"line":545},[365,2906,911],{"class":408},[365,2908,2909],{"class":367,"line":813},[365,2910,586],{"emptyLinePlaceholder":54},[365,2912,2913,2915,2918,2920,2922,2924,2926,2928,2930,2932,2935,2937,2939,2941,2943,2945,2947,2949,2951,2953,2956,2958],{"class":367,"line":821},[365,2914,603],{"class":602},[365,2916,2917],{"class":388}," locale ",[365,2919,609],{"class":392},[365,2921,654],{"class":388},[365,2923,1984],{"class":1757},[365,2925,409],{"class":408},[365,2927,1647],{"class":404},[365,2929,377],{"class":408},[365,2931,418],{"class":417},[365,2933,2934],{"class":421},"default-locale",[365,2936,424],{"class":417},[365,2938,427],{"class":388},[365,2940,2339],{"class":404},[365,2942,377],{"class":408},[365,2944,2824],{"class":404},[365,2946,409],{"class":408},[365,2948,2891],{"class":404},[365,2950,377],{"class":408},[365,2952,418],{"class":417},[365,2954,2955],{"class":421},"en_US",[365,2957,424],{"class":417},[365,2959,887],{"class":408},[960,2961,2963],{"id":2962},"reading-configs-in-swiftui","Reading configs in SwiftUI",[264,2965,2966,2968,2969,2971],{},[322,2967,1937],{}," is synchronous and makes no network calls, so it is safe to call directly from a ",[322,2970,331],{},". That gives you the current value, but the view will not re-render on its own when the value changes.",[264,2973,2974,2975,2978,2979,2981,2982,2985],{},"To have the view follow a config, drive a ",[322,2976,2977],{},"@State"," from ",[322,2980,1941],{}," inside a ",[322,2983,2984],{},".task",". The stream yields the current value immediately, so there is no frame where the view shows something other than the default before the first value arrives:",[356,2987,2990],{"className":380,"code":2988,"filename":2989,"language":253,"meta":361,"style":361},"import ConfigDirector\nimport SwiftUI\n\nstruct DarkModeToggle: View {\n    let client: ConfigDirectorClient\n\n    @State private var isOn = false\n\n    var body: some View {\n        Toggle(\"Dark mode\", isOn: $isOn)\n            .task {\n                for await value in client.values(for: \"dark-mode\", default: false) {\n                    isOn = value\n                }\n            }\n    }\n}\n","DarkModeToggle.swift",[322,2991,2992,2998,3004,3008,3022,3029,3033,3050,3054,3066,3091,3100,3141,3151,3155,3160,3164],{"__ignoreMap":361},[365,2993,2994,2996],{"class":367,"line":368},[365,2995,577],{"class":576},[365,2997,581],{"class":580},[365,2999,3000,3002],{"class":367,"line":398},[365,3001,577],{"class":576},[365,3003,714],{"class":580},[365,3005,3006],{"class":367,"line":448},[365,3007,586],{"emptyLinePlaceholder":54},[365,3009,3010,3012,3015,3017,3020],{"class":367,"line":454},[365,3011,732],{"class":726},[365,3013,3014],{"class":580}," DarkModeToggle",[365,3016,377],{"class":408},[365,3018,3019],{"class":580}," View ",[365,3021,743],{"class":408},[365,3023,3024,3026],{"class":367,"line":464},[365,3025,1250],{"class":602},[365,3027,3028],{"class":388}," client: ConfigDirectorClient\n",[365,3030,3031],{"class":367,"line":475},[365,3032,586],{"emptyLinePlaceholder":54},[365,3034,3035,3037,3039,3041,3043,3045,3047],{"class":367,"line":492},[365,3036,748],{"class":392},[365,3038,751],{"class":726},[365,3040,754],{"class":602},[365,3042,757],{"class":602},[365,3044,2167],{"class":388},[365,3046,609],{"class":392},[365,3048,3049],{"class":2344}," false\n",[365,3051,3052],{"class":367,"line":537},[365,3053,586],{"emptyLinePlaceholder":54},[365,3055,3056,3058,3060,3062,3064],{"class":367,"line":545},[365,3057,791],{"class":602},[365,3059,794],{"class":388},[365,3061,797],{"class":602},[365,3063,3019],{"class":388},[365,3065,743],{"class":408},[365,3067,3068,3071,3073,3075,3078,3080,3082,3084,3086,3089],{"class":367,"line":813},[365,3069,3070],{"class":404},"        Toggle",[365,3072,409],{"class":408},[365,3074,424],{"class":417},[365,3076,3077],{"class":421},"Dark mode",[365,3079,424],{"class":417},[365,3081,427],{"class":388},[365,3083,2233],{"class":404},[365,3085,377],{"class":408},[365,3087,3088],{"class":388}," $isOn",[365,3090,632],{"class":408},[365,3092,3093,3096,3098],{"class":367,"line":821},[365,3094,3095],{"class":388},"            .",[365,3097,842],{"class":404},[365,3099,810],{"class":408},[365,3101,3102,3105,3107,3110,3112,3114,3116,3118,3120,3122,3124,3127,3129,3131,3133,3135,3137,3139],{"class":367,"line":837},[365,3103,3104],{"class":576},"                for",[365,3106,1650],{"class":576},[365,3108,3109],{"class":388}," value ",[365,3111,1656],{"class":576},[365,3113,654],{"class":388},[365,3115,2376],{"class":1757},[365,3117,409],{"class":408},[365,3119,1647],{"class":404},[365,3121,377],{"class":408},[365,3123,418],{"class":417},[365,3125,3126],{"class":421},"dark-mode",[365,3128,424],{"class":417},[365,3130,427],{"class":388},[365,3132,2339],{"class":404},[365,3134,377],{"class":408},[365,3136,2345],{"class":2344},[365,3138,442],{"class":408},[365,3140,810],{"class":408},[365,3142,3143,3146,3148],{"class":367,"line":847},[365,3144,3145],{"class":388},"                    isOn ",[365,3147,609],{"class":392},[365,3149,3150],{"class":388}," value\n",[365,3152,3153],{"class":367,"line":890},[365,3154,893],{"class":408},[365,3156,3157],{"class":367,"line":896},[365,3158,3159],{"class":408},"            }\n",[365,3161,3162],{"class":367,"line":902},[365,3163,905],{"class":408},[365,3165,3166],{"class":367,"line":908},[365,3167,911],{"class":408},[665,3169,3170,3172,3173,3176],{},[322,3171,2984],{}," cancels its work when the view disappears and starts it again when the view returns, which ends and re-subscribes the stream for you. Use ",[322,3174,3175],{},".task(id:)"," when the config key or the default value can change, so the stream is replaced when they do.",[259,3178,3180],{"id":3179},"update-the-user-context","Update the user context",[264,3182,3183],{},"A user context can be provided when initializing the client:",[356,3185,3187],{"className":380,"code":3186,"filename":569,"language":253,"meta":361,"style":361},"import ConfigDirector\n\nlet client = try ConfigDirectorClient(clientSDKKey: \"YOUR-CLIENT-SDK-KEY\")\n\nawait client.initialize(\n    context: ConfigDirectorContext(\n        id: \"12345\",\n        name: \"Example User\",\n        traits: [\n            \u002F\u002F Any arbitrary traits which can be referenced in targeting rules\n            \"region\": \"North America\",\n        ]\n    )\n)\n",[322,3188,3189,3195,3199,3225,3229,3239,3250,3266,3281,3290,3295,3316,3321,3325],{"__ignoreMap":361},[365,3190,3191,3193],{"class":367,"line":368},[365,3192,577],{"class":576},[365,3194,581],{"class":580},[365,3196,3197],{"class":367,"line":398},[365,3198,586],{"emptyLinePlaceholder":54},[365,3200,3201,3203,3205,3207,3209,3211,3213,3215,3217,3219,3221,3223],{"class":367,"line":448},[365,3202,603],{"class":602},[365,3204,606],{"class":388},[365,3206,609],{"class":392},[365,3208,612],{"class":576},[365,3210,615],{"class":404},[365,3212,409],{"class":408},[365,3214,620],{"class":404},[365,3216,377],{"class":408},[365,3218,418],{"class":417},[365,3220,627],{"class":421},[365,3222,424],{"class":417},[365,3224,632],{"class":408},[365,3226,3227],{"class":367,"line":454},[365,3228,586],{"emptyLinePlaceholder":54},[365,3230,3231,3233,3235,3237],{"class":367,"line":464},[365,3232,651],{"class":576},[365,3234,654],{"class":388},[365,3236,657],{"class":404},[365,3238,472],{"class":408},[365,3240,3241,3244,3246,3248],{"class":367,"line":475},[365,3242,3243],{"class":404},"    context",[365,3245,377],{"class":408},[365,3247,870],{"class":404},[365,3249,472],{"class":408},[365,3251,3252,3255,3257,3259,3262,3264],{"class":367,"line":492},[365,3253,3254],{"class":404},"        id",[365,3256,377],{"class":408},[365,3258,418],{"class":417},[365,3260,3261],{"class":421},"12345",[365,3263,424],{"class":417},[365,3265,445],{"class":388},[365,3267,3268,3270,3272,3274,3277,3279],{"class":367,"line":537},[365,3269,478],{"class":404},[365,3271,377],{"class":408},[365,3273,418],{"class":417},[365,3275,3276],{"class":421},"Example User",[365,3278,424],{"class":417},[365,3280,445],{"class":388},[365,3282,3283,3286,3288],{"class":367,"line":545},[365,3284,3285],{"class":404},"        traits",[365,3287,377],{"class":408},[365,3289,395],{"class":388},[365,3291,3292],{"class":367,"line":813},[365,3293,3294],{"class":591},"            \u002F\u002F Any arbitrary traits which can be referenced in targeting rules\n",[365,3296,3297,3300,3303,3305,3307,3309,3312,3314],{"class":367,"line":821},[365,3298,3299],{"class":417},"            \"",[365,3301,3302],{"class":421},"region",[365,3304,424],{"class":417},[365,3306,377],{"class":392},[365,3308,418],{"class":417},[365,3310,3311],{"class":421},"North America",[365,3313,424],{"class":417},[365,3315,445],{"class":388},[365,3317,3318],{"class":367,"line":837},[365,3319,3320],{"class":388},"        ]\n",[365,3322,3323],{"class":367,"line":847},[365,3324,1095],{"class":408},[365,3326,3327],{"class":367,"line":890},[365,3328,632],{"class":408},[264,3330,3331,3332,377],{},"The user context can also be updated via ",[322,3333,3334],{},"updateContext",[356,3336,3338],{"className":380,"code":3337,"filename":2296,"language":253,"meta":361,"style":361},"await client.updateContext(\n    ConfigDirectorContext(\n        id: \"654321\",\n        name: \"Another User\",\n        traits: [\"region\": \"Australia\"]\n    )\n)\n\n\u002F\u002F Update it to an anonymous context when a user signs out. Leaving `id` unset\n\u002F\u002F makes the server derive a stable identifier from this SDK instance.\nawait client.updateContext(ConfigDirectorContext(isAnonymous: true))\n",[322,3339,3340,3350,3357,3372,3387,3413,3417,3421,3425,3430,3435],{"__ignoreMap":361},[365,3341,3342,3344,3346,3348],{"class":367,"line":368},[365,3343,651],{"class":576},[365,3345,654],{"class":388},[365,3347,3334],{"class":404},[365,3349,472],{"class":408},[365,3351,3352,3355],{"class":367,"line":398},[365,3353,3354],{"class":404},"    ConfigDirectorContext",[365,3356,472],{"class":408},[365,3358,3359,3361,3363,3365,3368,3370],{"class":367,"line":448},[365,3360,3254],{"class":404},[365,3362,377],{"class":408},[365,3364,418],{"class":417},[365,3366,3367],{"class":421},"654321",[365,3369,424],{"class":417},[365,3371,445],{"class":388},[365,3373,3374,3376,3378,3380,3383,3385],{"class":367,"line":454},[365,3375,478],{"class":404},[365,3377,377],{"class":408},[365,3379,418],{"class":417},[365,3381,3382],{"class":421},"Another User",[365,3384,424],{"class":417},[365,3386,445],{"class":388},[365,3388,3389,3391,3393,3396,3398,3400,3402,3404,3406,3409,3411],{"class":367,"line":464},[365,3390,3285],{"class":404},[365,3392,377],{"class":408},[365,3394,3395],{"class":388}," [",[365,3397,424],{"class":417},[365,3399,3302],{"class":421},[365,3401,424],{"class":417},[365,3403,377],{"class":392},[365,3405,418],{"class":417},[365,3407,3408],{"class":421},"Australia",[365,3410,424],{"class":417},[365,3412,534],{"class":388},[365,3414,3415],{"class":367,"line":475},[365,3416,1095],{"class":408},[365,3418,3419],{"class":367,"line":492},[365,3420,632],{"class":408},[365,3422,3423],{"class":367,"line":537},[365,3424,586],{"emptyLinePlaceholder":54},[365,3426,3427],{"class":367,"line":545},[365,3428,3429],{"class":591},"\u002F\u002F Update it to an anonymous context when a user signs out. Leaving `id` unset\n",[365,3431,3432],{"class":367,"line":813},[365,3433,3434],{"class":591},"\u002F\u002F makes the server derive a stable identifier from this SDK instance.\n",[365,3436,3437,3439,3441,3443,3445,3448,3450,3453,3455,3458],{"class":367,"line":821},[365,3438,651],{"class":576},[365,3440,654],{"class":388},[365,3442,3334],{"class":404},[365,3444,409],{"class":408},[365,3446,3447],{"class":404},"ConfigDirectorContext",[365,3449,409],{"class":408},[365,3451,3452],{"class":404},"isAnonymous",[365,3454,377],{"class":408},[365,3456,3457],{"class":2344}," true",[365,3459,887],{"class":408},[665,3461,3462,3463,3466,3467,3469],{},"In client SDKs (browser and mobile), updating the user context re-establishes a new connection to ConfigDirector servers with the new context. While the new connection is in flight, config values will continue to evaluate to the currently cached values from the prior user context.",[3464,3465],"br",{},"\nAwaiting ",[322,3468,3334],{}," will wait until the new config values are downloaded or the connection times out. In the case of a timeout, the client will continue to attempt to connect with the new context in the background.",[264,3471,3472,3473,3475],{},"Traits are written as ordinary Swift literals. Strings, integers, doubles, booleans, arrays, dictionaries and ",[322,3474,1924],{}," are all accepted:",[356,3477,3479],{"className":380,"code":3478,"filename":2296,"language":253,"meta":361,"style":361},"await client.updateContext(\n    ConfigDirectorContext(\n        id: \"user-123\",\n        name: \"Ada Lovelace\",\n        traits: [\n            \"plan\": \"pro\",\n            \"seats\": 12,\n            \"beta\": true,\n            \"regions\": [\"us-east\", \"eu-west\"],\n        ]\n    )\n)\n",[322,3480,3481,3491,3497,3511,3526,3534,3554,3570,3585,3616,3620,3624],{"__ignoreMap":361},[365,3482,3483,3485,3487,3489],{"class":367,"line":368},[365,3484,651],{"class":576},[365,3486,654],{"class":388},[365,3488,3334],{"class":404},[365,3490,472],{"class":408},[365,3492,3493,3495],{"class":367,"line":398},[365,3494,3354],{"class":404},[365,3496,472],{"class":408},[365,3498,3499,3501,3503,3505,3507,3509],{"class":367,"line":448},[365,3500,3254],{"class":404},[365,3502,377],{"class":408},[365,3504,418],{"class":417},[365,3506,882],{"class":421},[365,3508,424],{"class":417},[365,3510,445],{"class":388},[365,3512,3513,3515,3517,3519,3522,3524],{"class":367,"line":454},[365,3514,478],{"class":404},[365,3516,377],{"class":408},[365,3518,418],{"class":417},[365,3520,3521],{"class":421},"Ada Lovelace",[365,3523,424],{"class":417},[365,3525,445],{"class":388},[365,3527,3528,3530,3532],{"class":367,"line":464},[365,3529,3285],{"class":404},[365,3531,377],{"class":408},[365,3533,395],{"class":388},[365,3535,3536,3538,3541,3543,3545,3547,3550,3552],{"class":367,"line":475},[365,3537,3299],{"class":417},[365,3539,3540],{"class":421},"plan",[365,3542,424],{"class":417},[365,3544,377],{"class":392},[365,3546,418],{"class":417},[365,3548,3549],{"class":421},"pro",[365,3551,424],{"class":417},[365,3553,445],{"class":388},[365,3555,3556,3558,3561,3563,3565,3568],{"class":367,"line":492},[365,3557,3299],{"class":417},[365,3559,3560],{"class":421},"seats",[365,3562,424],{"class":417},[365,3564,377],{"class":392},[365,3566,3567],{"class":1595}," 12",[365,3569,445],{"class":388},[365,3571,3572,3574,3577,3579,3581,3583],{"class":367,"line":537},[365,3573,3299],{"class":417},[365,3575,3576],{"class":421},"beta",[365,3578,424],{"class":417},[365,3580,377],{"class":392},[365,3582,3457],{"class":2344},[365,3584,445],{"class":388},[365,3586,3587,3589,3592,3594,3596,3598,3600,3603,3605,3607,3609,3612,3614],{"class":367,"line":545},[365,3588,3299],{"class":417},[365,3590,3591],{"class":421},"regions",[365,3593,424],{"class":417},[365,3595,377],{"class":392},[365,3597,3395],{"class":388},[365,3599,424],{"class":417},[365,3601,3602],{"class":421},"us-east",[365,3604,424],{"class":417},[365,3606,427],{"class":388},[365,3608,424],{"class":417},[365,3610,3611],{"class":421},"eu-west",[365,3613,424],{"class":417},[365,3615,451],{"class":388},[365,3617,3618],{"class":367,"line":813},[365,3619,3320],{"class":388},[365,3621,3622],{"class":367,"line":821},[365,3623,1095],{"class":408},[365,3625,3626],{"class":367,"line":837},[365,3627,632],{"class":408},[264,3629,3630,3631,3633,3634,3636,3637,3639,3640,3642],{},"For a signed-out user, set ",[322,3632,3452],{}," to ",[322,3635,1513],{},". The values are still used to evaluate targeting rules, but the context is not persisted and does not appear in the dashboard. Leaving ",[322,3638,875],{}," unset makes the ConfigDirector server derive an identifier from the SDK instance, so the user keeps the same place in percentage rollouts for as long as that client instance lives; a new client instance gets a new identifier, which can move the user into a different percentile. Pass your own ",[322,3641,875],{}," when a rollout must stay stable across app launches.",[259,3644,3646],{"id":3645},"other-useful-client-features","Other useful client features",[264,3648,3649],{},"The client provides additional properties and methods.",[960,3651,3652],{"id":865},[322,3653,865],{},[264,3655,3656,3657,3659,3660,3662,3663,3665,3666,3668],{},"Returns the current user context (which may be ",[322,3658,1924],{},"). When calling ",[322,3661,3334],{},", the ",[322,3664,865],{}," is not immediately updated. The ",[322,3667,865],{}," is updated after the new connection for the new context succeeds (or times out and goes on retry).",[960,3670,3672],{"id":3671},"isready",[322,3673,688],{},[264,3675,3676,3677,3679,3680,3682,3683,3685,3686,3688,3689,3691,3692,3694,3695,3697,3698,3700],{},"Returns a ",[322,3678,2184],{}," indicating if the client has been successfully initialized and is ready to evaluate configs for the given user context. It is initially ",[322,3681,1498],{}," and becomes ",[322,3684,1513],{}," after ",[322,3687,657],{}," succeeds.\nUpon calling ",[322,3690,3334],{}," it becomes ",[322,3693,1498],{}," again and it is set to ",[322,3696,1513],{}," once ",[322,3699,3334],{}," succeeds.",[960,3702,3704],{"id":3703},"isinitializing",[322,3705,3706],{},"isInitializing",[264,3708,3676,3709,3711,3712,3714,3715,3717,3718,3720,3721,3723,3724,3726,3727,3730,3731,1204,3733,3736],{},[322,3710,2184],{}," indicating whether the client is trying to get its very first config state from the server. It is ",[322,3713,1498],{}," on creation, becomes ",[322,3716,1513],{}," when ",[322,3719,657],{}," is called on a client that has never received config state, stays ",[322,3722,1513],{}," through timeouts and retries, and becomes ",[322,3725,1498],{}," when the first config state arrives, when an unrecoverable connection error stops the retries, or on ",[322,3728,3729],{},"close()",". ",[322,3732,3334],{},[322,3734,3735],{},"resumeNetwork"," never set it. This is useful to show a loading state instead of transitioning from the in-code default value to the evaluated value on a slow connection.",[960,3738,3740,1204,3742],{"id":3739},"pausenetwork-and-resumenetwork",[322,3741,1502],{},[322,3743,1505],{},[264,3745,3746,3748,3749,3751,3752,1412,3754,858],{},[322,3747,1502],{}," releases the network connection without discarding config state, event streams, or watch streams, and ",[322,3750,1505],{}," re-establishes it using the last context given to ",[322,3753,657],{},[322,3755,3334],{},[264,3757,3758,3759,3633,3761,3763],{},"The client already does this on its own while the app is backgrounded, so these are only needed if you set ",[322,3760,1490],{},[322,3762,1498],{}," in order to manage the connection yourself.",[960,3765,3767],{"id":3766},"close",[322,3768,3729],{},[264,3770,3771],{},"Closes the connection, every watch stream, and every event stream, and reports whatever telemetry is left. The client cannot be used afterwards.",[264,3773,3774,3775,3777],{},"The client closes itself when it is released, so calling ",[322,3776,3729],{}," is only necessary to shut it down while a reference to it is still held.",[259,3779,3781],{"id":3780},"test-your-code","Test your code",[264,3783,3784,3785,3788,3789,3792],{},"Use the SDK's testing library, the ",[322,3786,3787],{},"ConfigDirectorTesting"," product of the same package, to test the code that reads your configs and flags. It creates a ",[351,3790,3791],{},"test client",": the SDK's real client connected to an in-memory server that your test controls. Only the connection to ConfigDirector, the telemetry, and the app lifecycle observer are replaced. Everything else is the same code that runs in production, so the code under test behaves exactly as it does against ConfigDirector, and no network connection is opened and no telemetry is sent. The product ships in the package you already depend on, so there is nothing else to add; link it into your test target only.",[356,3794,3796],{"className":380,"code":3795,"filename":376,"language":253,"meta":361,"style":361},".testTarget(\n    name: \"YourAppTests\",\n    dependencies: [\n        \"YourApp\",\n        .product(name: \"ConfigDirectorTesting\", package: \"configdirector-swift-sdk\"),\n    ]\n),\n",[322,3797,3798,3807,3823,3832,3844,3879,3884],{"__ignoreMap":361},[365,3799,3800,3802,3805],{"class":367,"line":368},[365,3801,858],{"class":388},[365,3803,3804],{"class":404},"testTarget",[365,3806,472],{"class":408},[365,3808,3809,3812,3814,3816,3819,3821],{"class":367,"line":398},[365,3810,3811],{"class":404},"    name",[365,3813,377],{"class":408},[365,3815,418],{"class":417},[365,3817,3818],{"class":421},"YourAppTests",[365,3820,424],{"class":417},[365,3822,445],{"class":388},[365,3824,3825,3828,3830],{"class":367,"line":448},[365,3826,3827],{"class":404},"    dependencies",[365,3829,377],{"class":408},[365,3831,395],{"class":388},[365,3833,3834,3837,3840,3842],{"class":367,"line":454},[365,3835,3836],{"class":417},"        \"",[365,3838,3839],{"class":421},"YourApp",[365,3841,424],{"class":417},[365,3843,445],{"class":388},[365,3845,3846,3849,3851,3853,3855,3857,3859,3861,3863,3865,3867,3869,3871,3873,3875,3877],{"class":367,"line":464},[365,3847,3848],{"class":388},"        .",[365,3850,503],{"class":404},[365,3852,409],{"class":408},[365,3854,508],{"class":404},[365,3856,377],{"class":408},[365,3858,418],{"class":417},[365,3860,3787],{"class":421},[365,3862,424],{"class":417},[365,3864,427],{"class":388},[365,3866,405],{"class":404},[365,3868,377],{"class":408},[365,3870,418],{"class":417},[365,3872,257],{"class":421},[365,3874,424],{"class":417},[365,3876,442],{"class":408},[365,3878,445],{"class":388},[365,3880,3881],{"class":367,"line":475},[365,3882,3883],{"class":388},"    ]\n",[365,3885,3886,3888],{"class":367,"line":492},[365,3887,442],{"class":408},[365,3889,445],{"class":388},[264,3891,3892,3893,3895,3896,3899],{},"In an Xcode project, add the ",[322,3894,3787],{}," library to your test target under ",[351,3897,3898],{},"Frameworks and Libraries","; the package itself is already added for the app.",[356,3901,3904],{"className":380,"code":3902,"filename":3903,"language":253,"meta":361,"style":361},"import ConfigDirectorTesting\nimport Testing\n\nstruct CheckoutTests {\n    @Test func enablesTheNewCheckoutWhenTheFlagIsOn() async {\n        let testClient = makeTestClient(values: [\"new-checkout\": true, \"max-items\": 20])\n        defer { testClient.client.close() }\n        await testClient.client.initialize()\n\n        let checkout = Checkout(client: testClient.client)\n        #expect(checkout.isNewCheckoutEnabled)\n\n        testClient.setValue(false, for: \"new-checkout\")\n        #expect(!checkout.isNewCheckoutEnabled)\n    }\n}\n","CheckoutTests.swift",[322,3905,3906,3913,3920,3924,3933,3954,4005,4021,4032,4036,4060,4072,4076,4102,4115,4119],{"__ignoreMap":361},[365,3907,3908,3910],{"class":367,"line":368},[365,3909,577],{"class":576},[365,3911,3912],{"class":580}," ConfigDirectorTesting\n",[365,3914,3915,3917],{"class":367,"line":398},[365,3916,577],{"class":576},[365,3918,3919],{"class":580}," Testing\n",[365,3921,3922],{"class":367,"line":448},[365,3923,586],{"emptyLinePlaceholder":54},[365,3925,3926,3928,3931],{"class":367,"line":454},[365,3927,732],{"class":726},[365,3929,3930],{"class":580}," CheckoutTests",[365,3932,810],{"class":408},[365,3934,3935,3937,3940,3943,3946,3949,3952],{"class":367,"line":464},[365,3936,748],{"class":392},[365,3938,3939],{"class":726},"Test",[365,3941,3942],{"class":726}," func",[365,3944,3945],{"class":1270}," enablesTheNewCheckoutWhenTheFlagIsOn",[365,3947,3948],{"class":408},"()",[365,3950,3951],{"class":726}," async",[365,3953,810],{"class":408},[365,3955,3956,3959,3962,3964,3967,3969,3971,3973,3975,3977,3980,3982,3984,3986,3988,3990,3993,3995,3997,4000,4003],{"class":367,"line":475},[365,3957,3958],{"class":602},"        let",[365,3960,3961],{"class":388}," testClient ",[365,3963,609],{"class":392},[365,3965,3966],{"class":404}," makeTestClient",[365,3968,409],{"class":408},[365,3970,2376],{"class":404},[365,3972,377],{"class":408},[365,3974,3395],{"class":388},[365,3976,424],{"class":417},[365,3978,3979],{"class":421},"new-checkout",[365,3981,424],{"class":417},[365,3983,377],{"class":392},[365,3985,3457],{"class":2344},[365,3987,427],{"class":388},[365,3989,424],{"class":417},[365,3991,3992],{"class":421},"max-items",[365,3994,424],{"class":417},[365,3996,377],{"class":392},[365,3998,3999],{"class":1595}," 20",[365,4001,4002],{"class":388},"]",[365,4004,632],{"class":408},[365,4006,4007,4010,4012,4015,4017,4019],{"class":367,"line":492},[365,4008,4009],{"class":576},"        defer",[365,4011,2197],{"class":408},[365,4013,4014],{"class":388}," testClient.client.",[365,4016,3766],{"class":404},[365,4018,3948],{"class":408},[365,4020,2203],{"class":408},[365,4022,4023,4026,4028,4030],{"class":367,"line":537},[365,4024,4025],{"class":576},"        await",[365,4027,4014],{"class":388},[365,4029,657],{"class":404},[365,4031,660],{"class":408},[365,4033,4034],{"class":367,"line":545},[365,4035,586],{"emptyLinePlaceholder":54},[365,4037,4038,4040,4043,4045,4048,4050,4053,4055,4058],{"class":367,"line":813},[365,4039,3958],{"class":602},[365,4041,4042],{"class":388}," checkout ",[365,4044,609],{"class":392},[365,4046,4047],{"class":404}," Checkout",[365,4049,409],{"class":408},[365,4051,4052],{"class":404},"client",[365,4054,377],{"class":408},[365,4056,4057],{"class":388}," testClient.client",[365,4059,632],{"class":408},[365,4061,4062,4065,4067,4070],{"class":367,"line":821},[365,4063,4064],{"class":404},"        #expect",[365,4066,409],{"class":408},[365,4068,4069],{"class":388},"checkout.isNewCheckoutEnabled",[365,4071,632],{"class":408},[365,4073,4074],{"class":367,"line":837},[365,4075,586],{"emptyLinePlaceholder":54},[365,4077,4078,4081,4084,4086,4088,4090,4092,4094,4096,4098,4100],{"class":367,"line":847},[365,4079,4080],{"class":388},"        testClient.",[365,4082,4083],{"class":404},"setValue",[365,4085,409],{"class":408},[365,4087,1498],{"class":2344},[365,4089,427],{"class":388},[365,4091,1647],{"class":404},[365,4093,377],{"class":408},[365,4095,418],{"class":417},[365,4097,3979],{"class":421},[365,4099,424],{"class":417},[365,4101,632],{"class":408},[365,4103,4104,4106,4108,4111,4113],{"class":367,"line":890},[365,4105,4064],{"class":404},[365,4107,409],{"class":408},[365,4109,4110],{"class":392},"!",[365,4112,4069],{"class":388},[365,4114,632],{"class":408},[365,4116,4117],{"class":367,"line":896},[365,4118,905],{"class":408},[365,4120,4121],{"class":367,"line":902},[365,4122,911],{"class":408},[264,4124,4125,4128,4129,4132,4133,4135,4136,4138],{},[322,4126,4127],{},"testClient.client"," is a ",[322,4130,4131],{},"ConfigDirectorClient",", so it goes anywhere your code accepts one. It starts uninitialized, like a production client, because the code under test usually owns the call to ",[322,4134,657],{},"; with nothing held or failed, ",[322,4137,657],{}," completes at once with the client ready. Close it when the test is done, as your production code would.",[960,4140,4142],{"id":4141},"watching-values","Watching values",[264,4144,4145,4147,4148,4151],{},[322,4146,1941],{}," streams work as they do in production: a stream yields the current value when it is created and then every time the evaluated value changes, so a test reads the next element after each change. A SwiftUI view driven by such a stream, as in ",[341,4149,2963],{"href":4150},"#reading-configs-in-swiftui",", follows the test client the same way.",[356,4153,4156],{"className":380,"code":4154,"filename":4155,"language":253,"meta":361,"style":361},"let testClient = makeTestClient(values: [\"greeting\": \"hello\"])\ndefer { testClient.client.close() }\nvar greetings = testClient.client.values(for: \"greeting\", default: \"none\").makeAsyncIterator()\n#expect(await greetings.next() == \"none\")\n\nawait testClient.client.initialize()\n#expect(await greetings.next() == \"hello\")\n\ntestClient.setValue(\"hi\", for: \"greeting\")\n#expect(await greetings.next() == \"hi\")\n","GreetingTests.swift",[322,4157,4158,4196,4211,4258,4286,4290,4300,4324,4328,4358],{"__ignoreMap":361},[365,4159,4160,4162,4164,4166,4168,4170,4172,4174,4176,4178,4181,4183,4185,4187,4190,4192,4194],{"class":367,"line":368},[365,4161,603],{"class":602},[365,4163,3961],{"class":388},[365,4165,609],{"class":392},[365,4167,3966],{"class":404},[365,4169,409],{"class":408},[365,4171,2376],{"class":404},[365,4173,377],{"class":408},[365,4175,3395],{"class":388},[365,4177,424],{"class":417},[365,4179,4180],{"class":421},"greeting",[365,4182,424],{"class":417},[365,4184,377],{"class":392},[365,4186,418],{"class":417},[365,4188,4189],{"class":421},"hello",[365,4191,424],{"class":417},[365,4193,4002],{"class":388},[365,4195,632],{"class":408},[365,4197,4198,4201,4203,4205,4207,4209],{"class":367,"line":398},[365,4199,4200],{"class":576},"defer",[365,4202,2197],{"class":408},[365,4204,4014],{"class":388},[365,4206,3766],{"class":404},[365,4208,3948],{"class":408},[365,4210,2203],{"class":408},[365,4212,4213,4216,4219,4221,4223,4225,4227,4229,4231,4233,4235,4237,4239,4241,4243,4245,4247,4249,4251,4253,4256],{"class":367,"line":448},[365,4214,4215],{"class":602},"var",[365,4217,4218],{"class":388}," greetings ",[365,4220,609],{"class":392},[365,4222,4014],{"class":388},[365,4224,2376],{"class":1757},[365,4226,409],{"class":408},[365,4228,1647],{"class":404},[365,4230,377],{"class":408},[365,4232,418],{"class":417},[365,4234,4180],{"class":421},[365,4236,424],{"class":417},[365,4238,427],{"class":388},[365,4240,2339],{"class":404},[365,4242,377],{"class":408},[365,4244,418],{"class":417},[365,4246,1824],{"class":421},[365,4248,424],{"class":417},[365,4250,442],{"class":408},[365,4252,858],{"class":388},[365,4254,4255],{"class":404},"makeAsyncIterator",[365,4257,660],{"class":408},[365,4259,4260,4263,4265,4267,4270,4273,4275,4278,4280,4282,4284],{"class":367,"line":454},[365,4261,4262],{"class":404},"#expect",[365,4264,409],{"class":408},[365,4266,651],{"class":576},[365,4268,4269],{"class":388}," greetings.",[365,4271,4272],{"class":404},"next",[365,4274,3948],{"class":408},[365,4276,4277],{"class":392}," ==",[365,4279,418],{"class":417},[365,4281,1824],{"class":421},[365,4283,424],{"class":417},[365,4285,632],{"class":408},[365,4287,4288],{"class":367,"line":464},[365,4289,586],{"emptyLinePlaceholder":54},[365,4291,4292,4294,4296,4298],{"class":367,"line":475},[365,4293,651],{"class":576},[365,4295,4014],{"class":388},[365,4297,657],{"class":404},[365,4299,660],{"class":408},[365,4301,4302,4304,4306,4308,4310,4312,4314,4316,4318,4320,4322],{"class":367,"line":492},[365,4303,4262],{"class":404},[365,4305,409],{"class":408},[365,4307,651],{"class":576},[365,4309,4269],{"class":388},[365,4311,4272],{"class":404},[365,4313,3948],{"class":408},[365,4315,4277],{"class":392},[365,4317,418],{"class":417},[365,4319,4189],{"class":421},[365,4321,424],{"class":417},[365,4323,632],{"class":408},[365,4325,4326],{"class":367,"line":537},[365,4327,586],{"emptyLinePlaceholder":54},[365,4329,4330,4333,4335,4337,4339,4342,4344,4346,4348,4350,4352,4354,4356],{"class":367,"line":545},[365,4331,4332],{"class":388},"testClient.",[365,4334,4083],{"class":404},[365,4336,409],{"class":408},[365,4338,424],{"class":417},[365,4340,4341],{"class":421},"hi",[365,4343,424],{"class":417},[365,4345,427],{"class":388},[365,4347,1647],{"class":404},[365,4349,377],{"class":408},[365,4351,418],{"class":417},[365,4353,4180],{"class":421},[365,4355,424],{"class":417},[365,4357,632],{"class":408},[365,4359,4360,4362,4364,4366,4368,4370,4372,4374,4376,4378,4380],{"class":367,"line":813},[365,4361,4262],{"class":404},[365,4363,409],{"class":408},[365,4365,651],{"class":576},[365,4367,4269],{"class":388},[365,4369,4272],{"class":404},[365,4371,3948],{"class":408},[365,4373,4277],{"class":392},[365,4375,418],{"class":417},[365,4377,4341],{"class":421},[365,4379,424],{"class":417},[365,4381,632],{"class":408},[264,4383,4384,4385,4387,4388,4390],{},"A stream keeps only the newest value, so two ",[322,4386,4083],{}," calls before the next read arrive as one element, and ",[322,4389,1618],{}," keeps the newest 256 events.",[960,4392,4393],{"id":2376},"Values",[264,4395,4396,427,4398,4400,4401,4404,4405,4408,4409,4411,4412,4415,4416,4419,4420,4423,4424,4427,4428,4431,4432,4435],{},[322,4397,2376],{},[322,4399,4083],{},", and ",[322,4402,4403],{},"replaceValues"," take ",[322,4406,4407],{},"TestValue","s, usually written as literals, and the config type follows from the case: ",[322,4410,1513],{}," is a boolean config, ",[322,4413,4414],{},"20"," an integer config, ",[322,4417,4418],{},"2.5"," a float config, ",[322,4421,4422],{},"\"Ada\""," a string config, ",[322,4425,4426],{},"[\"theme\": \"dark\", \"limit\": 3]"," a JSON object, and ",[322,4429,4430],{},"[\"x\", \"y\"]"," a JSON array. A string is always a string config, so JSON text meant as a JSON config is given as an object or array literal. Every value is served to every context; a test that needs different values per context is written as one test per value. There is no null value; ",[322,4433,4434],{},"removeValue(for:)"," removes one. A blank key or a number that is not finite is a programming error and stops the test with a precondition failure.",[264,4437,4438,4439,4442,4443,4445,4446,4449,4450,4453,4454,4456,4457,4400,4460,4463,4464,4467,4468,4470,4471,4473],{},"Reads behave as they do in production: ",[322,4440,4441],{},"setValue(true, for: \"k\")"," read as a ",[322,4444,1294],{}," returns the in-code default value and publishes a ",[322,4447,4448],{},"typeMismatch"," evaluation, ",[322,4451,4452],{},"setValue(2.5, for: \"k\")"," read as an ",[322,4455,2436],{}," returns ",[322,4458,4459],{},"2",[322,4461,4462],{},"setValue(\"\", for: \"k\")"," serves the in-code default value with the ",[322,4465,4466],{},"valueMissing"," reason. A JSON object is encoded with its keys in sorted order, and ",[322,4469,2557],{}," decodes it into your ",[322,4472,2561],{}," type.",[960,4475,4477],{"id":4476},"controls","Controls",[268,4479,4480,4490],{},[271,4481,4482],{},[274,4483,4484,4487],{},[277,4485,4486],{},"Control",[277,4488,4489],{},"Effect",[284,4491,4492,4512,4533,4543,4566,4581,4596,4614],{},[274,4493,4494,4499],{},[289,4495,4496],{},[322,4497,4498],{},"setValue(_:for:)",[289,4500,4501,4502,4504,4505,4508,4509,4511],{},"Stores the value and, once the client is connected, delivers an update carrying only that key. Reads see it when ",[322,4503,4083],{}," returns; ",[322,4506,4507],{},"values(for:)"," streams of the key and ",[322,4510,1618],{}," yield it.",[274,4513,4514,4518],{},[289,4515,4516],{},[322,4517,4434],{},[289,4519,4520,4521,4524,4525,4527,4528,4530,4531,858],{},"Removes the value and delivers a full update without it. Reads return the in-code default value with the ",[322,4522,4523],{},"configStateMissing"," reason, ",[322,4526,4507],{}," streams of the key yield the default, and ",[322,4529,1729],{}," lists the key in ",[322,4532,1770],{},[274,4534,4535,4540],{},[289,4536,4537],{},[322,4538,4539],{},"replaceValues(_:)",[289,4541,4542],{},"Replaces every stored value, disarms any armed hold or failure, and delivers a full update. Use it to reset a test client shared across tests.",[274,4544,4545,4550],{},[289,4546,4547],{},[322,4548,4549],{},"holdInitialization()",[289,4551,4552,4553,4555,4556,1412,4559,4562,4563,4565],{},"The next ",[322,4554,657],{}," waits until ",[322,4557,4558],{},"completeInitialization()",[322,4560,4561],{},"failInitialization()",", or until the client's ",[322,4564,1463],{}," elapses.",[274,4567,4568,4572],{},[289,4569,4570],{},[322,4571,4558],{},[289,4573,4574,4575,4577,4578,4580],{},"Delivers the stored values to the held ",[322,4576,657],{},", so the client is ready when it returns, and lets ",[322,4579,657],{}," complete. Called while a hold is armed but not picked up, it disarms the hold.",[274,4582,4583,4587],{},[289,4584,4585],{},[322,4586,4561],{},[289,4588,4589,4590,4592,4593,4595],{},"Fails the held ",[322,4591,657],{}," the way an invalid SDK key does: it completes promptly, the client is not ready, and an error is logged. Called with no ",[322,4594,657],{}," held, it arms the next one to fail.",[274,4597,4598,4609],{},[289,4599,4600,427,4603,427,4606],{},[322,4601,4602],{},"holdContextUpdate()",[322,4604,4605],{},"completeContextUpdate()",[322,4607,4608],{},"failContextUpdate()",[289,4610,4611,4612,858],{},"The same for the next ",[322,4613,3334],{},[274,4615,4616,4621],{},[289,4617,4618],{},[322,4619,4620],{},"contextUpdates",[289,4622,4623,4624,1204,4626,4628,4629,4631,4632,4634],{},"The context of every ",[322,4625,657],{},[322,4627,3334],{}," call, in order. ",[322,4630,657],{}," without a context records an empty context, and ",[322,4633,3735],{}," is not recorded.",[264,4636,4637,4638,4640,4641,4643,4644,4646,4647,4649,4650,4653],{},"The initialization controls act only on ",[322,4639,657],{}," and the context update controls only on ",[322,4642,3334],{},"; ",[322,4645,3735],{}," is never held or failed. After a failed attempt, the next attempt succeeds and delivers the values stored in the meantime. A held ",[322,4648,657],{}," suspends its caller, so start it in a ",[322,4651,4652],{},"Task"," and drive it from the test:",[356,4655,4658],{"className":380,"code":4656,"filename":4657,"language":253,"meta":361,"style":361},"let testClient = makeTestClient(values: [\"new-checkout\": true], timeout: 0.5)\ndefer { testClient.client.close() }\ntestClient.holdInitialization()\n\nlet initialization = Task { await testClient.client.initialize() }\ntry await Task.sleep(nanoseconds: 50_000_000)\n#expect(testClient.client.isReady == false)\n#expect(testClient.client.isInitializing)\n\ntestClient.completeInitialization()\nawait initialization.value\n#expect(testClient.client.isReady)\n","LoadingTests.swift",[322,4659,4660,4700,4714,4723,4727,4751,4776,4792,4803,4807,4816,4826],{"__ignoreMap":361},[365,4661,4662,4664,4666,4668,4670,4672,4674,4676,4678,4680,4682,4684,4686,4688,4691,4693,4695,4698],{"class":367,"line":368},[365,4663,603],{"class":602},[365,4665,3961],{"class":388},[365,4667,609],{"class":392},[365,4669,3966],{"class":404},[365,4671,409],{"class":408},[365,4673,2376],{"class":404},[365,4675,377],{"class":408},[365,4677,3395],{"class":388},[365,4679,424],{"class":417},[365,4681,3979],{"class":421},[365,4683,424],{"class":417},[365,4685,377],{"class":392},[365,4687,3457],{"class":2344},[365,4689,4690],{"class":388},"], ",[365,4692,1463],{"class":404},[365,4694,377],{"class":408},[365,4696,4697],{"class":1595}," 0.5",[365,4699,632],{"class":408},[365,4701,4702,4704,4706,4708,4710,4712],{"class":367,"line":398},[365,4703,4200],{"class":576},[365,4705,2197],{"class":408},[365,4707,4014],{"class":388},[365,4709,3766],{"class":404},[365,4711,3948],{"class":408},[365,4713,2203],{"class":408},[365,4715,4716,4718,4721],{"class":367,"line":448},[365,4717,4332],{"class":388},[365,4719,4720],{"class":404},"holdInitialization",[365,4722,660],{"class":408},[365,4724,4725],{"class":367,"line":454},[365,4726,586],{"emptyLinePlaceholder":54},[365,4728,4729,4731,4734,4736,4739,4741,4743,4745,4747,4749],{"class":367,"line":464},[365,4730,603],{"class":602},[365,4732,4733],{"class":388}," initialization ",[365,4735,609],{"class":392},[365,4737,4738],{"class":404}," Task",[365,4740,2197],{"class":408},[365,4742,1650],{"class":576},[365,4744,4014],{"class":388},[365,4746,657],{"class":404},[365,4748,3948],{"class":408},[365,4750,2203],{"class":408},[365,4752,4753,4756,4758,4761,4764,4766,4769,4771,4774],{"class":367,"line":475},[365,4754,4755],{"class":576},"try",[365,4757,1650],{"class":576},[365,4759,4760],{"class":388}," Task.",[365,4762,4763],{"class":404},"sleep",[365,4765,409],{"class":408},[365,4767,4768],{"class":404},"nanoseconds",[365,4770,377],{"class":408},[365,4772,4773],{"class":1595}," 50_000_000",[365,4775,632],{"class":408},[365,4777,4778,4780,4782,4785,4788,4790],{"class":367,"line":492},[365,4779,4262],{"class":404},[365,4781,409],{"class":408},[365,4783,4784],{"class":388},"testClient.client.isReady ",[365,4786,4787],{"class":392},"==",[365,4789,2345],{"class":2344},[365,4791,632],{"class":408},[365,4793,4794,4796,4798,4801],{"class":367,"line":537},[365,4795,4262],{"class":404},[365,4797,409],{"class":408},[365,4799,4800],{"class":388},"testClient.client.isInitializing",[365,4802,632],{"class":408},[365,4804,4805],{"class":367,"line":545},[365,4806,586],{"emptyLinePlaceholder":54},[365,4808,4809,4811,4814],{"class":367,"line":813},[365,4810,4332],{"class":388},[365,4812,4813],{"class":404},"completeInitialization",[365,4815,660],{"class":408},[365,4817,4818,4820,4823],{"class":367,"line":821},[365,4819,651],{"class":576},[365,4821,4822],{"class":388}," initialization.",[365,4824,4825],{"class":1757},"value\n",[365,4827,4828,4830,4832,4835],{"class":367,"line":837},[365,4829,4262],{"class":404},[365,4831,409],{"class":408},[365,4833,4834],{"class":388},"testClient.client.isReady",[365,4836,632],{"class":408},[960,4838,4840],{"id":4839},"options","Options",[264,4842,4843,4846,4847,427,4849,4851,4852,4854,4855,4858,4859,4861],{},[322,4844,4845],{},"makeTestClient"," takes ",[322,4848,2376],{},[322,4850,1463],{}," (the client's connection timeout, which bounds how long a held attempt waits; defaults to the SDK's production timeout of 3 seconds), and ",[322,4853,1102],{}," (defaults to the SDK's ",[322,4856,4857],{},"ConsoleLogger",", which writes to the unified logging system; pass a ",[322,4860,1117],{}," of your own to capture what the client logs).",[960,4863,4865],{"id":4864},"what-to-expect","What to expect",[1397,4867,4868,4882,4903,4913,4926,4936],{},[556,4869,4870,4871,4873,4874,4876,4877,4876,4879,4881],{},"Under the test client, ",[322,4872,657],{}," publishes ",[322,4875,1787],{},", then ",[322,4878,1684],{},[322,4880,1729],{},", all before it returns.",[556,4883,4884,4885,1412,4888,4890,4891,4893,4894,4896,4897,4899,4900,4902],{},"A held attempt that times out, or that is interrupted by ",[322,4886,4887],{},"pauseNetwork",[322,4889,3766],{},", leaves the client not ready until the next attempt, applies the context it was given, and logs the SDK's timeout warning, which says the client will keep retrying, as production streaming would. A held ",[322,4892,657],{}," ended by ",[322,4895,3766],{}," logs it too, and ",[322,4898,3706],{}," stays ",[322,4901,1513],{}," after a timeout, as it does in production until the first config state arrives.",[556,4904,4905,4906,427,4908,4400,4910,4912],{},"The client runs ",[322,4907,657],{},[322,4909,3334],{},[322,4911,3735],{}," one at a time, so an attempt started while another is held waits for it to be completed, failed, or ended.",[556,4914,4915,4917,4918,4920,4921,4923,4924,858],{},[322,4916,4507],{}," streams yield on creation and then only when the evaluated value changes, as in production, so a ",[322,4919,4083],{}," to the value already served yields nothing, while ",[322,4922,1618],{}," still carries the ",[322,4925,1729],{},[556,4927,4928,4930,4931,1204,4933,4935],{},[322,4929,1490],{}," has no effect: the test client does not observe the app lifecycle. Call ",[322,4932,4887],{},[322,4934,3735],{}," to test that path; values set while paused are delivered on resume.",[556,4937,4938,4939,4941],{},"After ",[322,4940,3766],{},", the test client's controls are silent no-ops, every stream finishes, and no task from the SDK is left running.",[4943,4944,4945],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sptTA, html code.shiki .sptTA{--shiki-light:#6182B8;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sw1J6, html code.shiki .sw1J6{--shiki-light:#F76D47;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sFwrP, html code.shiki .sFwrP{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#24292E;--shiki-default-font-style:inherit;--shiki-dark:#E1E4E8;--shiki-dark-font-style:inherit}html pre.shiki code .s95qv, html code.shiki .s95qv{--shiki-light:#6182B8;--shiki-light-font-style:italic;--shiki-default:#6F42C1;--shiki-default-font-style:inherit;--shiki-dark:#B392F0;--shiki-dark-font-style:inherit}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sfo-9, html code.shiki .sfo-9{--shiki-light:#90A4AE;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .syTEX, html code.shiki .syTEX{--shiki-light:#FF5370;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":361,"searchDepth":398,"depth":398,"links":4947},[4948,4949,4950,4954,4959,4960,4968],{"id":261,"depth":398,"text":262},{"id":335,"depth":398,"text":336},{"id":550,"depth":398,"text":551,"children":4951},[4952,4953],{"id":962,"depth":448,"text":963},{"id":1618,"depth":448,"text":1619},{"id":2273,"depth":398,"text":2274,"children":4955},[4956,4957,4958],{"id":2550,"depth":448,"text":2551},{"id":2776,"depth":448,"text":2777},{"id":2962,"depth":448,"text":2963},{"id":3179,"depth":398,"text":3180},{"id":3645,"depth":398,"text":3646,"children":4961},[4962,4963,4964,4965,4967],{"id":865,"depth":448,"text":865},{"id":3671,"depth":448,"text":688},{"id":3703,"depth":448,"text":3706},{"id":3739,"depth":448,"text":4966},"pauseNetwork() and resumeNetwork()",{"id":3766,"depth":448,"text":3729},{"id":3780,"depth":398,"text":3781,"children":4969},[4970,4971,4972,4973,4974],{"id":4141,"depth":448,"text":4142},{"id":2376,"depth":448,"text":4393},{"id":4476,"depth":448,"text":4477},{"id":4839,"depth":448,"text":4840},{"id":4864,"depth":448,"text":4865},"Install and configure the Swift SDK, evaluate configs and feature flags, and keep SwiftUI views current as values change","md",null,{"modifiedAt":4979},"2026-10-12T00:22:49.000Z",{"title":125,"icon":128},{"title":246,"description":4975},"saAkz1rxaICuz0-b6Gnd9P3JpuipH1l0s3qeh3QM3a4",[4984,4986],{"title":120,"path":121,"stem":122,"description":4985,"icon":123,"children":-1},"Install and configure the Flutter SDK, and evaluate configs and feature flags on every platform Flutter targets",{"title":130,"path":131,"stem":132,"description":4987,"icon":133,"children":-1},"Install and configure the Android SDK, evaluate configs and feature flags, and keep your UI current as values change",1791783864944]