fix(ios): open custom schemes instead of always reporting failure - #2
Open
CodyPChristian wants to merge 1 commit into
Open
Conversation
`Browser.Open` gated `UIApplication.open` behind `canOpenURL`. For a custom
scheme, iOS answers `canOpenURL` false unless that scheme is listed in the
CALLING app's `LSApplicationQueriesSchemes` — whether or not anything on the
device actually handles it.
So `Browser::open('myapp://')` returns false on a phone with `myapp` installed,
and there is no way to tell that apart from a genuine failure. An app whose
target schemes are not known when its own Info.plist is written can never
satisfy the declaration requirement, so for those the guard reports "nothing can
open this" for every custom scheme, permanently.
`open`'s completion handler already answers the same question, without the
declaration requirement, and from what actually happened rather than a
pre-flight guess. Dropping the guard makes `success` mean what the docblock
already claims it means.
http/https is unaffected: `canOpenURL` is unconditionally true for those, which
is every example in the README.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
Browser.OpengatesUIApplication.openbehindcanOpenURL:For a custom scheme, iOS answers
canOpenURLfalse unless that scheme is listed in the calling app'sLSApplicationQueriesSchemes— regardless of whether anything on the device handles it.So
Browser::open('myapp://')returnsfalseon a phone that hasmyappinstalled, and there's no way to tell that apart from a real failure.That's awkward for any app that declares its target schemes up front, and impossible for one that can't. In our case a host app opens a per-tenant companion app whose scheme is issued long after the host's
Info.plistis written — so the guard reports "nothing can open this" for every custom scheme, permanently.The change
Drop the guard and let
open's completion handler report the result.It already answers the same question, without the declaration requirement, and answers it from what actually happened rather than from a pre-flight guess. That makes
successmean what the docblock says it means: "True if successfully opened."Why this shouldn't regress anything
canOpenURLis unconditionally true for those — no declaration needed — so the guard never rejected one. That's every example in the README.UIApplication.openwith a scheme nothing handles doesn't throw; the completion handler receivesfalse, which is exactly what theelsebranch was producing.The 2s semaphore timeout is untouched; the failure path now costs one async round-trip instead of returning immediately, which isn't observable.
Testing
vendor/bin/pest— 58 passed, 129 assertions, unchanged.The Swift isn't covered by that suite. Verified by building a real app against the branch: it compiles, launches, and the custom-scheme path now reaches
openinstead of short-circuiting.Also added a short note to the README's
open()section, since custom schemes weren't mentioned and thesuccessreturn is how you detect the target app isn't installed.