Skip to content

fix(ios): don't register iOS 26 only method in protocol block - #1301

Merged
FabianLars merged 1 commit into
tauri-apps:devfrom
velocitysystems:ios18-objc2-crash
Aug 7, 2026
Merged

fix(ios): don't register iOS 26 only method in protocol block#1301
FabianLars merged 1 commit into
tauri-apps:devfrom
velocitysystems:ios18-objc2-crash

Conversation

@velocitysystems

@velocitysystems velocitysystems commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Closes #1300.

Problem

preferredWindowingControlStyleForScene: (#1250, #1276) is an iOS 26 selector declared inside the unsafe impl UIWindowSceneDelegate block. objc2 validates protocol-block selectors against the runtime protocol, and iOS 18's UIWindowSceneDelegate doesn't declare it, so class registration panics on launch:

failed overriding protocol method -[UIWindowSceneDelegate preferredWindowingControlStyleForScene:]: method not found

The check is #[cfg(debug_assertions)], so this is debug builds only — release builds register the method and iOS 18 simply never calls it. It breaks cargo tauri ios dev on iOS 18.

Fix

Empty the protocol block and register the method from a plain impl, which performs no protocol lookup. unsafe impl UISceneDelegate is untouched.

The resulting class is unchanged, verified against objc2 0.6.4: add_protocol() runs independently of any methods, so conformance survives the empty block; builder.add_method() sits outside the debug_assertions check in both paths, so iOS 26 still resolves the selector; and finish() only checks required methods, of which UIWindowSceneDelegate has none.

Trade-off: gives up objc2's typo check on this one selector.

Why not the build-script gate from wry#1781

That fix reads the build host's OS version and cfg-gates the method out, which works on macOS because the host is the runtime. On iOS it isn't — the host is macOS and the runtime is a separate simulator or device. Since Xcode 26 is needed to compile this selector at all, the host check would pass and the panic would remain. The only iOS-side build-time signal is the deployment target, which is a floor rather than the runtime version, so gating on it reduces to #[cfg(not(debug_assertions))] — losing .minimal windowing controls on iPadOS 26 in every debug build while checking nothing, since the check only runs in debug and the method would be absent there.

Also considered: [profile.dev.package.objc2] debug-assertions = false (objc2#796) works, but cargo only honours profiles from the workspace root, so tao can't ship it. objc2's disable-encoding-assertions feature doesn't cover __macro_helpers/define_class.rs. Remaining alternatives are in #1300.

Includes a TODO to move the method back into the protocol block once objc2 0.7.0 fixes the check (objc2#645).

Testing

cargo check --target aarch64-apple-ios and cargo test pass.

  • Verified fix on an iOS 18 simulator
  • Verified no regression on an iOS 26.5 simulator (debug) + iOS 26.5.2 device (release)

@velocitysystems
velocitysystems marked this pull request as ready for review August 6, 2026 20:52
@velocitysystems
velocitysystems requested a review from a team as a code owner August 6, 2026 20:52
@FabianLars
FabianLars merged commit 95636d5 into tauri-apps:dev Aug 7, 2026
2 checks passed
@github-actions github-actions Bot mentioned this pull request Aug 7, 2026
@velocitysystems
velocitysystems deleted the ios18-objc2-crash branch August 7, 2026 09:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] iOS 18: debug builds panic on launch registering an iOS 26-only method

2 participants