Skip to content

Fix threading issues on ios#43

Merged
jkasprzyk17 merged 4 commits into
gmi-software:mainfrom
adamivancza:fix-threading-issues-on-ios
Jul 3, 2026
Merged

Fix threading issues on ios#43
jkasprzyk17 merged 4 commits into
gmi-software:mainfrom
adamivancza:fix-threading-issues-on-ios

Conversation

@adamivancza

Copy link
Copy Markdown
Contributor

Summary

  • Serialize iOS HybridMapView state access and provider adapter mutations onto the main thread.
  • Keep provider adapters synchronous and unchanged, with the thread boundary at the RN/Nitro entry point.
  • Resolve Promise-returning reads (fetchCamera, getVisibleRegion) asynchronously on main to avoid blocking worklet/background callers.

Why

Nitro hybrid objects can be accessed from worklet/background runtimes, but UIKit/MapKit access must happen on the main thread. This prevents off-main map mutations and cached-state races.

Observed warning before this fix:

[UIKitCore] +[UIView setAnimationsEnabled:] being called from a background thread.
Performing any operation from a background thread on UIView or a subclass is not supported

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c9ad4d0d-d60a-4b37-870e-3e4e7775761f

📥 Commits

Reviewing files that changed from the base of the PR and between 64c2acd and 94a73a1.

📒 Files selected for processing (1)
  • package/ios/HybridMapView.swift

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Improved map stability when views are mounted, recycled, or updated quickly.
    • Fixed cases where camera actions or map interactions could fail after the view changed state.
    • Ensured map updates and callbacks are applied on the main thread for more reliable behavior.
    • Reduced issues with stale map state by resetting and re-syncing map features more safely during lifecycle changes.

Walkthrough

HybridMapView.swift now tracks mount state with a generation-checked lifecycle, routes adapter access through main-thread helpers, and rejects stale async camera work after recycle. Property, callback, camera, and teardown paths now use backing fields plus explicit main-thread propagation.

Changes

Main-thread lifecycle and adapter routing

Layer / File(s) Summary
Lifecycle tracking fields and helpers
package/ios/HybridMapView.swift
Adds lifecycleLock, lifecycleGeneration, adapter storage, and recycled-state tracking used to invalidate stale async work.
Lifecycle validation and adapter install
package/ios/HybridMapView.swift
Introduces lifecycle snapshot, activation, recycle, and validation helpers, and enforces main-thread adapter installation.
Main-thread execution utilities
package/ios/HybridMapView.swift
Adds onMain and promiseOnMain helpers that run work on the main thread and reject with MapView is not mounted when lifecycle validation fails.
Property, callback, camera, and recycle routing
package/ios/HybridMapView.swift
Moves map properties, callback wiring, camera methods, and prepareForRecycle onto the new main-thread and lifecycle-checked adapter flow.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant JS as JS caller
  participant View as HybridMapView
  participant Main as Main thread
  participant Adapter as Map adapter

  JS->>View: fetchCamera()
  View->>Main: promiseOnMain(snapshot)
  Main->>Main: validateActiveLifecycle(snapshot)
  alt lifecycle mismatch
    Main-->>JS: reject "MapView is not mounted"
  else lifecycle matches
    Main->>Adapter: currentAdapter(matching: snapshot)
    Adapter-->>Main: camera data
    Main-->>JS: resolve camera data
  end
Loading
🚥 Pre-merge checks | ✅ 6
✅ Passed checks (6 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main change: fixing iOS threading issues in HybridMapView.
Description check ✅ Passed The description clearly describes the iOS main-thread serialization and async camera reads in this PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Security Check ✅ Passed No security-relevant behavior changed; diff only swaps public getters for private backing fields in main-thread syncState.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@package/ios/HybridMapView.swift`:
- Around line 400-428: The synchronous camera methods in HybridMapView are
bypassing the recycle safety check and can recreate a new adapter after
prepareForRecycle(). Update applyCamera, animateCamera, and fitToCoordinates to
enforce the same recycle-generation guard used by fetchCamera and
getVisibleRegion, either by making currentAdapter() reject access once recycled
or by checking the generation before calling it so stale calls fail instead of
reattaching the map.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e45387cd-d86c-46cd-bd02-1400a5075cc8

📥 Commits

Reviewing files that changed from the base of the PR and between c4278b9 and 64c2acd.

📒 Files selected for processing (1)
  • package/ios/HybridMapView.swift

Comment thread package/ios/HybridMapView.swift
@jkasprzyk17 jkasprzyk17 added the review Waiting for review by colleagues label Jul 3, 2026
@jkasprzyk17

Copy link
Copy Markdown
Contributor

Great work on this PR 👏

The main-thread confinement and lifecycle guard look solid, and the fix for the CodeRabbit feedback in the third commit makes sense.

One small follow-up before merge: in syncState, please use the backing _ fields directly instead of the public getters. Since syncState is already called from installAdapter on the main thread, lines like:

adapter.onRegionChange = onRegionChange
adapter.markers = markers

add unnecessary onMain hops. It would be cleaner and more consistent with prepareForRecycle to do:

adapter.onRegionChange = _onRegionChange
adapter.markers = _markers
// ... same for the other callback/overlay fields

Once that’s in, I’m happy to approve. Thanks!

@adamivancza

Copy link
Copy Markdown
Contributor Author

Great work on this PR 👏

The main-thread confinement and lifecycle guard look solid, and the fix for the CodeRabbit feedback in the third commit makes sense.

One small follow-up before merge: in syncState, please use the backing _ fields directly instead of the public getters. Since syncState is already called from installAdapter on the main thread, lines like:

adapter.onRegionChange = onRegionChange
adapter.markers = markers

add unnecessary onMain hops. It would be cleaner and more consistent with prepareForRecycle to do:

adapter.onRegionChange = _onRegionChange
adapter.markers = _markers
// ... same for the other callback/overlay fields

Once that’s in, I’m happy to approve. Thanks!

oh indeed - totally missed that! fixed!

@jkasprzyk17

Copy link
Copy Markdown
Contributor

Looks good with the syncState fix. Thanks!

Happy to approve.

@jkasprzyk17 jkasprzyk17 merged commit 36f8472 into gmi-software:main Jul 3, 2026
4 checks passed
@adamivancza adamivancza deleted the fix-threading-issues-on-ios branch July 3, 2026 16:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review Waiting for review by colleagues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants