{"platform":{"slug":"ios","platform":"iOS","documentationVersion":"v2.0.2","officialDocumentationUrl":"https://developer.mappls.com/documentation/sdk/ios-sdk/","repositoryGuideSlugs":["mappls-ui-widget-ios-distribution","mappls-nearby-ui-ios-distribution","mappls-direction-ui-ios-distribution","mappls-geofence-ui-ios-distribution"],"supportedComponents":["MapplsUIWidget 2.0.1","MapplsNearbyUI 2.0.0","MapplsDirectionUI 2.0.0","MapplsGeofenceUI 2.0.0","MapplsFeedbackUIKit 3.0.0","MapplsMap 6.1.4"],"lifecycleOwner":"One presenting UIViewController or SwiftUI representable owns presentation, delegate lifetime, dismissal, and cancellation.","returnBoundary":"Copy the documented delegate result into a Sendable application value before dismissing the provider controller.","cancellationBoundary":"Interactive dismissal, explicit cancel, delegate error, scene deactivation, and no result are represented separately.","credentialBoundary":"Bundle only the issued iOS configuration files for the exact bundle identity. Server tokens and cross-application configuration do not belong in the app.","productionChecks":["Swift Package versions match the documented release family","The delegate cannot outlive its presenting owner","Interactive dismissal records cancellation once","Scene restoration never reuses a stale candidate"],"scaffold":{"language":"swift","label":"Swift host contract","code":"struct PlaceSelection: Sendable {\n    let mapplsPin: String\n    let label: String\n}\n\nprotocol MapplsPlaceWidget: Sendable {\n    @MainActor func selectPlace() async throws -> PlaceSelection?\n}\n\n@MainActor\nfunc choose(using widget: any MapplsPlaceWidget) async throws -> PlaceSelection? {\n    guard let selected = try await widget.selectPlace() else { return nil }\n    precondition(selected.mapplsPin.range(of: #\"^[A-Za-z0-9]{6}$\"#, options: .regularExpression) != nil)\n    return selected // Repository commit happens outside the provider controller.\n}"},"verifiedAt":"2026-08-17"},"capability":{"slug":"place-search","title":"Place search and picker","stateModel":"selection","durableIdentity":"Mappls Pin plus application-owned display label","platforms":{"android":{"availability":"published","component":"Place Search Widget","version":"3.0.2","documentationUrl":"https://developer.mappls.com/documentation/sdk/android/"},"ios":{"availability":"published","component":"MapplsUIWidget","version":"2.0.1","documentationUrl":"https://developer.mappls.com/documentation/sdk/ios-sdk/"},"flutter":{"availability":"published","component":"Place Search Widget","version":"2.0.0","documentationUrl":"https://developer.mappls.com/documentation/sdk/flutter-sdk/"},"react-native":{"availability":"published","component":"Place Search Widget","version":"2.0.0","documentationUrl":"https://developer.mappls.com/documentation/sdk/react-native-sdk/"}}},"implementation":{"availability":"published","component":"MapplsUIWidget","version":"2.0.1","documentationUrl":"https://developer.mappls.com/documentation/sdk/ios-sdk/"},"readiness":"source-ready","lifecycle":[{"state":"idle","owner":"Application screen","evidence":"No provider controller, route, Promise, delegate, or listener is active."},{"state":"launching","owner":"Platform adapter","evidence":"One generation ID binds configuration, owner, and launch time."},{"state":"active","owner":"Provider widget under host lifecycle","evidence":"Background, recreation, close, and duplicate-launch behavior are observable."},{"state":"returned / cancelled / failed","owner":"Platform adapter","evidence":"Exactly one typed terminal result wins; late results are ignored."},{"state":"candidate","owner":"Application domain","evidence":"Validate and normalize mappls pin plus application-owned display label before committing."},{"state":"committed","owner":"Application repository","evidence":"Persist the normalized selection/draft with version, actor, source, and audit event."}],"stateOwnership":["One presenting UIViewController or SwiftUI representable owns presentation, delegate lifetime, dismissal, and cancellation.","Copy the documented delegate result into a Sendable application value before dismissing the provider controller.","Interactive dismissal, explicit cancel, delegate error, scene deactivation, and no result are represented separately.","The durable record is mappls pin plus application-owned display label; never retain a provider view/controller or opaque bridge result."],"acceptanceTests":["Swift Package versions match the documented release family","The delegate cannot outlive its presenting owner","Interactive dismissal records cancellation once","Scene restoration never reuses a stale candidate","Permission/configuration denied","Offline and slow provider response","Cancel before and after a candidate appears","Host edit invalidates a stale selection","Duplicate callback/Promise result commits once","Accessibility, focus return, and a non-widget fallback"],"samples":[{"language":"swift","label":"Swift host contract","code":"struct PlaceSelection: Sendable {\n    let mapplsPin: String\n    let label: String\n}\n\nprotocol MapplsPlaceWidget: Sendable {\n    @MainActor func selectPlace() async throws -> PlaceSelection?\n}\n\n@MainActor\nfunc choose(using widget: any MapplsPlaceWidget) async throws -> PlaceSelection? {\n    guard let selected = try await widget.selectPlace() else { return nil }\n    precondition(selected.mapplsPin.range(of: #\"^[A-Za-z0-9]{6}$\"#, options: .regularExpression) != nil)\n    return selected // Repository commit happens outside the provider controller.\n}"}],"evidenceBoundary":"The current iOS overview lists MapplsUIWidget 2.0.1 under documentation v2.0.2. Confirm the exact package, configuration, callback schema, and entitlement in the selected guide before binding the adapter.","websiteUrl":"/tools/widgets/native?platform=ios&capability=place-search"}