Android, iOS, Flutter, and React Native remain distinct release and lifecycle boundaries.
One capability. Four runtimes. Six lifecycle states.
Choose the exact mobile path you are shipping. The matrix preserves current version evidence, exposes missing overview coverage, and makes the host application—not the provider UI—the owner of durable state.
Place search, nearby, directions, geofence, and feedback are evaluated independently.
Every pairing is represented, including gaps in the current first-party overview.
The remaining 3 paths require product selection—not a guessed package.
Geofence editor for iOS
- Documentation
- v2.0.2
- Component
- MapplsGeofenceUI
- Version
- 2.0.0
- State model
- draft
The current iOS overview lists MapplsGeofenceUI 2.0.0 under documentation v2.0.2. Confirm the exact package, configuration, callback schema, and entitlement in the selected guide before binding the adapter.
Twenty paths. Every gap visible.
“Not listed” means the current overview does not establish a package. It does not mean the capability is impossible, and it never licenses reuse of another platform’s package.
Make every return, cancellation, and late callback explainable.
The generated scaffold deliberately stops at an application-owned candidate. Your repository decides whether and how that candidate becomes durable.
idle
No provider controller, route, Promise, delegate, or listener is active.
launching
One generation ID binds configuration, owner, and launch time.
active
Background, recreation, close, and duplicate-launch behavior are observable.
returned / cancelled / failed
Exactly one typed terminal result wins; late results are ignored.
candidate
Validate and normalize versioned application geofence draft and provider rule identity after separate publication before committing.
committed
Persist the normalized selection/draft with version, actor, source, and audit event.
struct PlaceSelection: Sendable {
let mapplsPin: String
let label: String
}
protocol MapplsPlaceWidget: Sendable {
@MainActor func selectPlace() async throws -> PlaceSelection?
}
@MainActor
func choose(using widget: any MapplsPlaceWidget) async throws -> PlaceSelection? {
guard let selected = try await widget.selectPlace() else { return nil }
precondition(selected.mapplsPin.range(of: #"^[A-Za-z0-9]{6}$"#, options: .regularExpression) != nil)
return selected // Repository commit happens outside the provider controller.
}The widget is a collaborator, not your database.
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 versioned application geofence draft and provider rule identity after separate publication; never retain a provider view/controller or opaque bridge result.
Test the lifecycle you cannot demo.
Happy-path selection proves almost nothing about a production mobile integration.
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