canOpenURL Is Deprecated: What to Call Instead

Apple retired a method that has shipped since iOS 3.0 in three sentences: “canOpenURL: is deprecated. Attempt to open the URL and handle any failure instead of validating it first. Using universal links instead of custom URL schemes removes the need for this validation entirely.”1

The entry carries radar 179874781 and sits under UIKit, Deprecations, directly beneath the scene life cycle mandate that stops apps from launching.1 The neighboring entry names a consequence. The canOpenURL entry names none.

Each of the three sentences is a separate instruction, and only the second answers the question a developer actually has: what do I write instead? Apple’s answer changes the shape of the call, not just the name.

TL;DR

  • Apple deprecated canOpenURL(_:) at 27.0 on iOS, iPadOS, Mac Catalyst, tvOS, and visionOS, with the message “Prefer attempting to open URLs and handling any failures.”2 No removal version, no runtime consequence.
  • The change with teeth is a number, and it sits in the deprecated method’s own discussion rather than in any release note: “Apps linked on or after iOS 27 are limited to a maximum of 25 entries in the LSApplicationQueriesSchemes key,” down from 50.2 The trigger is the SDK you link against.
  • The mechanical swap is open(_:options:completionHandler:) and its Boolean, which needs no allowlist entry: “the open(_:options:completionHandler:) method isn’t constrained by the LSApplicationQueriesSchemes requirement.”2
  • One pattern loses its replacement, because canOpenURL answers before you draw anything while attempting answers by consequence: a success puts another app in the foreground.2 What survives is universalLinksOnly, an open option since iOS 10 that Apple has not deprecated: it “opens the URL only if the URL is a valid universal link and there is an installed app capable of opening that URL.”3
  • SwiftUI never shipped the method, and its completion Boolean already means “can open” rather than “did open.”415 Across seven of my shipping apps and 463 first-party Swift files, canOpenURL and LSApplicationQueriesSchemes each appear zero times.6

The deprecation with no consequence, and the number that has one

Apple wrote a deprecation, not a removal. The symbol page carries deprecatedAt 27.0 on all five platforms where UIApplication exists, and the abstract, discussion, return-value contract, and declaration all remain in place.2 No Apple page names a version in which the method stops working, and the nearest precedent points the other way: openURL(_:), deprecated at iOS 10.0, still has a page, and its note now reads “Calling this method has no effect.”7 A decade of deprecation produced a method that is inert rather than absent, which is precedent rather than a schedule.

The announcement is also narrower than the deprecation. The release note lives on a page Apple titles “iOS & iPadOS 27 Beta 4 Release Notes” and appears nowhere else, while the symbol metadata deprecates the method on tvOS and visionOS all the same, and neither Apple’s UIKit updates page for June 2026 nor the Xcode 27 release notes mention it at all.1289 The symbol page is the durable half of the record here.

Which makes the buried number the real story. Inside the deprecated method’s own discussion, in the same aside that requires the declaration in the first place: “Apps linked on or after iOS 15 are limited to a maximum of 50 entries in the LSApplicationQueriesSchemes key. Apps linked on or after iOS 27 are limited to a maximum of 25 entries in the LSApplicationQueriesSchemes key.”2

The allowlist outlives the deprecation of the only method it serves, and the ceiling halves for apps linked against the new SDK. Apple states the ceiling and stops there. Nothing says what happens past entry 25, and reading the aside’s two halves together gives a likely answer rather than a documented one: undeclared schemes always return false, so an app declaring 40 schemes that relinks probably starts treating 15 of them as absent. Apple never says which 15, or that truncation follows array order at all. Treat the mechanism as inference and the risk as real, because a false looks identical whether the app is missing or the declaration is.

The next paragraph of the same discussion carries a second limit, and the two are alternatives rather than additions. Apple keys them to the SDK you linked against: “If you link your app against an earlier version of iOS but it is running in iOS 9.0 or later, you can call this method up to 50 times. After reaching that limit, subsequent calls always return false. If the user reinstalls or upgrades the app, iOS resets the limit.”2 Read the condition. That budget belongs to apps linked before iOS 9, which is nothing you can ship today. Every current app lives under the other branch, the declaration ceiling, which is the one Apple cut from 50 entries to 25. Both spend down to the same silent false, and both are documented only inside the method Apple just deprecated.

The privacy reading is inference too. canOpenURL was the standard way to detect which apps a person had installed, a device signal rather than a link check, and Apple’s own definition of fingerprinting covers APIs “misused to access device signals to try to identify the device or user.”10 Apple never connects the two: the method appears on no required reason API list, and the release note, deprecation message, and symbol page all give a purely mechanical rationale.1210 A halved query ceiling fits the privacy story, and Apple has not written it down.

What canOpenURL actually promised

A true was a guarantee about the next call, not a description of the URL: “When this method returns true, iOS guarantees subsequent calls to the open(_:options:completionHandler:) method with the same URL will successfully launch an app that can handle the URL.”2 A false was ambiguous by design, with two causes and no way to tell which fired: “false if the device doesn’t have an installed app registered to handle the URL’s scheme, or if you haven’t declared the URL’s scheme in your Info.plist file.”2

Three things it never answered are easy to assume it did: “The return value doesn’t indicate the validity of the URL, whether the specified resource exists, or, in the case of a universal link, whether the device has an installed app registered to respond to the universal link.”2 The third clause matters for the migration Apple recommends, and it returns below.

The property that made the method structurally useful is the one nothing replaces. canOpenURL carries the nonisolated keyword in its declaration, and Apple states plainly that “you can call this method safely on a thread that isn’t the main thread.”2 A synchronous Boolean available off the main actor can gate a layout decision before anything renders.

Attempt and handle: the shape that changes

Apple’s replacement instruction is one clause long, and the before-and-after looks trivial.

// Before: validate, then open. Requires an Info.plist declaration.
let url = URL(string: "someapp://profile/42")!
if UIApplication.shared.canOpenURL(url) {
    UIApplication.shared.open(url)
} else {
    presentWebFallback()
}
<key>LSApplicationQueriesSchemes</key>
<array>
    <string>someapp</string>
</array>
// After: attempt, then handle. No declaration needed.
let url = URL(string: "someapp://profile/42")!
let opened = await UIApplication.shared.open(url)
if !opened {
    presentWebFallback()
}

The Info.plist entry disappears, and Apple says so directly: “Unlike this method, the open(_:options:completionHandler:) method isn’t constrained by the LSApplicationQueriesSchemes requirement. If an app is available to handle the URL, the system will launch it, even if you haven’t declared the scheme.”2 A codebase that migrates fully deletes the key, and with it the 25-entry problem.

Two differences survive the rewrite, and both are structural.

The first is isolation and timing. UIApplication’s declaration reads @MainActor class UIApplication, so open runs on the main actor, and its abstract calls it what it is: “Attempts to asynchronously open the resource at the specified URL.”1112 The synchronous, off-main-thread Boolean is gone, so validate-then-open logic sitting in a model layer, a background queue, or a non-isolated helper has to move or become async.

The second is that you can no longer ask privately. When the attempt succeeds, another app is in the foreground: “iOS launches that app and passes the URL to it. (Launching the app brings the other app to the foreground.)”12 The answer arrives as a side effect of acting on it. Apple documents nothing visible for the failing case, only that “the completion handler is called with the success parameter set to false,” but every pattern that needed the answer ahead of the action loses it: showing an open-in-another-app row only when the app is there, ordering a share sheet by what is installed, or picking a default among competing targets.12

Apple’s own documentation has not caught up either. The open(_:options:completionHandler:) page still instructs: “To determine whether an app is installed that is capable of handling the URL, call the canOpenURL(_:) method before calling this one.”12 The replacement’s page recommends the deprecated method.

The presence check that survives

One documented path answers canOpenURL’s question by attempting, with nothing user-visible when the answer is no. UIApplication.OpenExternalURLOptionsKey.universalLinksOnly has existed since iOS 10, Apple has not deprecated it, and the behavior is exactly a presence check: “the method opens the URL only if the URL is a valid universal link and there is an installed app capable of opening that URL.”3

// Presence check with no side effect when the app is absent.
let url = URL(string: "https://myphotoapp.example.com/albums?albumname=vacation")!
let installed = await UIApplication.shared.open(
    url,
    options: [.universalLinksOnly: true]
)
if !installed {
    presentWebFallback()   // nothing opened, nothing switched
}

The false branch is the valuable part. No browser launched, no app came forward, and the caller learned what canOpenURL used to tell it. The tradeoff hides in the option name: without it, an https attempt succeeds whenever a browser can take it, since “if no app is available to handle a universal link, iOS routes it to the person’s default browser, allowing the associated website to respond.”2 The option buys a meaningful Boolean by suppressing the fallback that makes universal links pleasant. Apple types the value as “an NSNumber object containing a Boolean value,” which a Swift true satisfies through Objective-C bridging.3

The price is architectural, and it is Apple’s third sentence. Universal links need a two-way association: “When someone installs your app, the system checks a file stored on your web server to verify that your website allows your app to open URLs on its behalf. Only you can store this file on your server, securing the association of your website and your app.”13 A server file you control is exactly what a custom scheme never required, which is why the migration works for your own app family and does nothing for a third party who publishes only theirapp://. Two documented surprises ride along: your app opening your own universal link does not route into your app, and a same-domain tap while browsing your site in Safari stays in Safari.13

Which is where the third clause from earlier lands: canOpenURL never answered the presence question for a universal link either.2 Migrating removes presence detection rather than porting it, because a plain https attempt already succeeds whether the app answered or only the website did. A pattern that worked only because custom schemes leaked installation state leaves with the schemes, and Apple’s release note frames the loss as the reason to migrate.

SwiftUI never had the method

The SwiftUI side is short, and the news is good. EnvironmentValues.openURL, OpenURLAction, and Link all carry availability from iOS 14.0 with no deprecation, and none of the three exposes a validity check.4514

What SwiftUI ships instead is attempt-and-handle with the semantics Apple now wants everywhere, and the completion parameter documentation says the Boolean answers the old question: “A closure the method calls after determining if it can open the URL, but possibly before fully opening the URL. The closure takes a Boolean value that indicates whether the method can open the URL.”15 Can open, not did open. Apple’s own example prints on it:

openURL(url) { accepted in
    print(accepted ? "Success" : "Failure")
}

Link exposes no Boolean at all and defers to the environment, where the default already implements the universal-link story: “the default action opens a Universal Link in the associated app if possible, or in the user’s default web browser if not.”5 A custom OpenURLAction returning .handled, .discarded, or .systemAction intercepts every Link and every markdown link in a Text that reads the action from that environment.5

One gap matters before planning a SwiftUI-only migration. OpenURLAction has no options dictionary. Its call signatures are callAsFunction(_:), callAsFunction(_:completion:), and the iOS 26 addition callAsFunction(_:prefersInApp:), and none of the three accepts universalLinksOnly.1518 A side-effect-free presence check still means calling UIApplication.shared.open.

Seven apps, 463 files, zero calls

I audited my own portfolio before writing about anyone else’s, expecting a migration list. There is nothing to migrate.6

App Swift files canOpenURL LSApplicationQueriesSchemes URL-opening call sites
Reps 77 0 0 5
Return 57 0 0 2
Banana List 55 0 0 2
Ace Citizenship 26 0 0 2
Water 34 0 0 0
ResumeGeni 71 0 0 12
Yawara 143 0 0 0
Total 463 0 0 23

The zero survived three passes of widening scope, out to every vendored Swift package and every file type in every repository.6 Nothing declares a queried scheme in 192 .plist, .pbxproj, .entitlements, and .xcconfig files either, which follows: an app with no canOpenURL call has no reason to declare one.

The reason is mundane and probably common. Of the 23 call sites, nine open a legal document, four hand off to the app’s own web product, two open census.gov from an alert so a user can find their representative, two open a job posting URL that arrives from an API, two are macOS-only file: exports, and one is UIApplication.openSettingsURLString behind a “Health Access Required” alert. None of those 20 queries another app, because every destination is either https, which Safari always answers, or a system URL. The remaining three carry all the interesting behavior.

The one place that validates before opening is not doing what the deprecation is about: ResumeGeni’s billing flow POSTs to /api/me/portal, then checks url.scheme == "https" on the URL the server returns, in case a compromised or buggy server hands the app a file: or custom-scheme URL.6 Apple’s note targets validating whether a target app exists and says nothing about trusting remote input, so deleting that guard would be a security regression, not a migration.

The other two are Banana List’s macOS handoffs, and one of them holds the only genuine presence check in the portfolio. The app asks NSWorkspace.shared.urlForApplication(withBundleIdentifier: "com.anthropic.claudefordesktop") != nil before handing a bundled .mcpb extension to Launch Services, with a nearby button opening claude.com/download for people who need the app first. The code comment names the motive: without the check, macOS shows its own “no application set to open the document” dialog.6 Different platform, and the most useful data point in the audit, because it catches the attempt-and-handle failure mode in the wild. A failed attempt is not always silent, and when the system speaks for you the user reads a system error instead of your fallback.

No repository declares applinks:, so no app here supports universal links, and Apple’s architectural fix is unpaid on my side too.6 A custom scheme costs an Info.plist entry; a universal link costs a file on a web server, an entitlement, and a domain you control.

Which points at where the real work sits: not first-party app code, but share sheets that reorder by installed app, “open in” pickers, and attribution SDKs, none of which a clean repository rules out.

The audit itself is easier here than elsewhere in the 27 cycle. Unlike the launch screen keys, which arrive from build settings and defeat a text search entirely, LSApplicationQueriesSchemes has no INFOPLIST_KEY_ equivalent in Apple’s build settings reference, so a grep is the right first move, and whose schemes appear in that array tells you which dependency wants the answer.16

FAQ

Does canOpenURL stop working in iOS 27?

No, and Apple has not said when it will. The symbol carries deprecatedAt 27.0, and every other part of the page, including the return-value contract, the guarantee about the following open call, the declaration ceiling, and the legacy call budget, remains documented.2 No removal version appears in the release note, on the symbol page, or in the Xcode 27 release notes.129 Plan for a warning and slow decay rather than a break.

What do I write instead, if I need to know whether the app is installed?

It depends on whether you control the target. If you do, publish a universal link and pass universalLinksOnly to open, which Apple documents as opening the URL only when it is a valid universal link with an installed app to take it, so a false means nothing opened and nothing switched.3 The cost is a two-way association file on your web server.13 If a third party publishes only a custom scheme, no replacement exists: canOpenURL still answers, still needs its Info.plist declaration, and the ceiling on that declaration halves to 25 entries for apps linked on or after iOS 27.2 SwiftUI code needs no change on this front, because openURL and Link never offered the check.414

Do I still need LSApplicationQueriesSchemes?

Only for canOpenURL. Apple’s Launch Services documentation defines the key entirely in terms of the deprecated method: it “specifies the URL schemes you want the app to be able to use with the canOpenURL: method of the UIApplication class.”17 The key has no page in Apple’s modern Information Property List reference at all, and the deprecated method’s discussion links to the legacy archive for it.217 The replacement needs nothing, because Apple exempts open from the declaration requirement outright.2 Finish migrating and the array goes away; keep one call and you keep the array, the declaration requirement, and the smaller ceiling.

Will the App Store reject a build with more than 25 entries?

No Apple page says so. The ceiling appears in one place, the discussion of canOpenURL(_:), and Apple phrases it as a limit on what the key holds rather than as a submission rule.2 Nothing in the iOS 27 release notes, the UIKit updates page, or the Xcode 27 release notes attaches a review consequence to it, and the documented symptom for a scheme the system treats as undeclared is a plain false at runtime.1289 The App Store Review Guidelines carry no occurrence of LSApplicationQueriesSchemes, canOpenURL, or the 25-entry figure, which is where a submission rule would live if one existed.19 So the failure to plan for is a wrong answer in your own code rather than a rejected build.

Key Takeaways

For iOS developers: - Replace if canOpenURL(url) { open(url) } with let opened = await open(url) and a fallback on !opened, then delete the matching LSApplicationQueriesSchemes entry once no call remains.2 - Keep any scheme check you run on a URL that arrives from a server. Apple’s note targets app-presence validation, not remote input, and the two look identical in a grep.

For teams shipping app-family deep links or SDKs: - Reach for universalLinksOnly rather than canOpenURL when you need a presence answer, and budget the associated-domains file it requires.313 It is the only documented check that leaves nothing user-visible when the app is missing. - Count your LSApplicationQueriesSchemes array before linking against the iOS 27 SDK. Anything past 25 entries lands outside the documented ceiling, and Apple’s symptom for an undeclared scheme is a plain false, which reads exactly like an app that is not installed.2

For release managers: - Do not schedule the deprecation as a release blocker. No removal date and no runtime consequence puts it behind the launch screen key that costs a rejection, the scene mandate that stops launches, and the @State macro that stops a build. - Treat the 25-entry ceiling as the one item with a real trigger, because it keys off the SDK you link against rather than the OS your users run.2


The 27 cycle keeps arriving in different weights, and reading the weight is how you spend the cycle well: the launch screen key blocks a submission, the scene mandate stops an app from launching, the @State macro stops a build, On Demand Resources starts a migration clock, and canOpenURL only warns. Manufacturing urgency around the warning wastes a cycle. The line worth watching sits in a discussion paragraph instead of a release note, and it is a number. The full series hub is the Apple Ecosystem Series.

References


  1. Apple, iOS & iPadOS 27 Release Notes, UIKit section, Deprecations (radar 179874781). The page titled itself “iOS & iPadOS 27 Beta 4 Release Notes” when checked, as did every other release-note page cited in this article, so treat all release-note wording here as provisional; the symbol pages’ availability metadata is the more durable record. Source of the complete entry quoted here: “canOpenURL: is deprecated. Attempt to open the URL and handle any failure instead of validating it first. Using universal links instead of custom URL schemes removes the need for this validation entirely.” The entry immediately follows the scene life cycle entry (radar 141837548), “Apps built with the latest SDK must adopt the scene-based life cycle or they fail to launch.” Verified against Apple’s documentation JSON on July 26, 2026, because the HTML page renders through JavaScript. The same JSON contains exactly one occurrence of canOpenURL and one of radar 179874781. The tvOS 27, visionOS 27, watchOS 27, and macOS 27 release notes were fetched the same day, titled “tvOS 27 Beta 4,” “visionOS 27 Beta 4,” “watchOS 27 Beta 4,” and “macOS 27 Golden Gate Beta 4” respectively, and contain zero occurrences of either string. 

  2. Apple, canOpenURL(_:), UIKit instance method reference. Declared nonisolated func canOpenURL(_ url: URL) -> Bool, introduced at iOS 3.0 (Mac Catalyst 13.1, tvOS 9.0, visionOS 1.0) and marked deprecatedAt 27.0 on iOS, iPadOS, Mac Catalyst, tvOS, and visionOS, each with the availability message “Prefer attempting to open URLs and handling any failures.” The page’s deprecation summary repeats two of the release note’s three sentences verbatim: “Attempt to open the URL and handle any failure instead of validating it first. Using universal links instead of custom URL schemes removes the need for this validation entirely.” Source of the return-value documentation (“false if the device doesn’t have an installed app registered to handle the URL’s scheme, or if you haven’t declared the URL’s scheme in your Info.plist file; otherwise, true”), the guarantee (“When this method returns true, iOS guarantees subsequent calls to the open(_:options:completionHandler:) method with the same URL will successfully launch an app that can handle the URL. The return value doesn’t indicate the validity of the URL, whether the specified resource exists, or, in the case of a universal link, whether the device has an installed app registered to respond to the universal link”), the threading note (“You can call this method safely on a thread that isn’t the main thread”), the allowlist aside quoted here including both ceilings (“Apps linked on or after iOS 15 are limited to a maximum of 50 entries in the LSApplicationQueriesSchemes key. Apps linked on or after iOS 27 are limited to a maximum of 25 entries in the LSApplicationQueriesSchemes key”), the runtime call budget quoted here (“If you link your app against an earlier version of iOS but it is running in iOS 9.0 or later, you can call this method up to 50 times. After reaching that limit, subsequent calls always return false. If the user reinstalls or upgrades the app, iOS resets the limit”), the exemption (“Unlike this method, the open(_:options:completionHandler:) method isn’t constrained by the LSApplicationQueriesSchemes requirement. If an app is available to handle the URL, the system will launch it, even if you haven’t declared the scheme”), and the universal-link fallback (“if no app is available to handle a universal link, iOS routes it to the person’s default browser, allowing the associated website to respond”). One sentence in the aside reads oddly as published: “This method always returns false for undeclared schemes, even if the device doesn’t have a registered app installed.” The claim about ambiguous false values in this article rests on the return-value section rather than on that sentence. Verified against Apple’s documentation JSON on July 26, 2026. 

  3. Apple, UIApplication.OpenExternalURLOptionsKey.universalLinksOnly, UIKit type property reference. Available since iOS 10.0 (Mac Catalyst 13.1, tvOS 10.0, visionOS 1.0), carrying no deprecation metadata as of July 26, 2026. Source of the abstract (“URLs must be universal links and have an app configured to open them”) and of the discussion quoted here: “When you include this key in the options dictionary of the open(_:options:completionHandler:) method, the method opens the URL only if the URL is a valid universal link and there is an installed app capable of opening that URL. The value of this key is an NSNumber object containing a Boolean value.” 

  4. Apple, EnvironmentValues.openURL, SwiftUI instance property reference. Declared @MainActor @preconcurrency var openURL: OpenURLAction, available from iOS 14.0, iPadOS 14.0, Mac Catalyst 14.0, macOS 11.0, tvOS 14.0, visionOS 1.0, and watchOS 7.0, with no deprecation metadata as of July 26, 2026. Source of the openURL(url) { accepted in ... } example reproduced here and of the default-action description quoted in this article. 

  5. Apple, OpenURLAction, SwiftUI structure reference. Declared @MainActor @preconcurrency struct OpenURLAction, available from iOS 14.0 with no deprecation metadata. Source of “The system provides a default open URL action with behavior that depends on the contents of the URL. For example, the default action opens a Universal Link in the associated app if possible, or in the user’s default web browser if not,” of the statement that a custom action applies to “the built-in Link view and Text views with markdown links, or links in attributed strings,” The Result members named in this article come from the child page, Apple, OpenURLAction.Result, which enumerates handled, discarded, systemAction, systemAction(_:), and the iOS 26 type method systemAction(_:prefersInApp:)

  6. Author’s survey of seven shipping Apple-platform projects (Reps, Return, Banana List, Ace Citizenship, Water, ResumeGeni, and Yawara) on macOS 26.5.2, July 26, 2026, using ripgrep over first-party Swift with build/, DerivedData/, .build/, Pods/, Carthage/, .swiftpm/, SourcePackages/, and package checkouts/ excluded. File coverage was reconciled find against rg per repository (77, 57, 55, 26, 34, 71, and 143 files) to confirm no gitignored first-party Swift was skipped. The canOpenURL zero was verified three ways: first-party Swift; Swift with --no-ignore --hidden, which includes build products and every vendored package checkout (3,946 Swift files in the ResumeGeni tree, 15,760 in the shared 941Kit tree); and all file types with --no-ignore. Zero in every pass, including third-party and vendored code. LSApplicationQueriesSchemes and INFOPLIST_KEY_LSApplicationQueriesSchemes returned zero across 192 .plist, .pbxproj, .entitlements, and .xcconfig files. The 23 call sites comprise six SwiftUI Link views, three UIApplication.shared.open calls, 12 openURL(...) calls (all in ResumeGeni, from six @Environment(\.openURL) declarations), and two NSWorkspace.shared.open calls in Banana List’s macOS code; the Link( count requires a word boundary, since a bare pattern also matches NavigationLink( and several project-specific ...Link( types. Zero SFSafariViewController and zero WKWebView usages exist in any project, and zero repositories declare applinks:. The ResumeGeni billing guard is Profile/ProfileView.swift:1746; the Banana List presence check and its explanatory comment are Banana List/SettingsView.swift:321 and :329, and the phrase “no application set to open the document” quoted in this article is that source comment’s wording rather than a transcription of the macOS dialog; Return’s Settings deep link is Return/ContentView.swift:222. Reps’ main app target declares SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator macosx"; no platform claim in this article derives from a *_DEPLOYMENT_TARGET key, and no app’s full platform reach is inferred from SUPPORTED_PLATFORMS, which only 40 of 80 build configurations in these projects set at all. 

  7. Apple, openURL(_:), UIKit instance method reference. Declared func openURL(_ url: URL) -> Bool, introduced at iOS 2.0 and deprecated at iOS 10.0 (Mac Catalyst 13.1). Source of the current deprecation note: “Calling this method has no effect. Use the open(_:options:completionHandler:) method instead.” Checked July 26, 2026. 

  8. Apple, UIKit updates, Apple Developer Documentation. The June 2026 section carries four subsections (General, App life cycle, Drag and drop, and Text views) and includes the scene life cycle mandate under App life cycle: “Starting in iOS 27, apps built with the latest SDK must use the scene-based life cycle or they fail to launch.” Searched for canOpenURL and LSApplicationQueriesSchemes on July 26, 2026; neither appears anywhere on the page. 

  9. Apple, Xcode 27 Release Notes. Searched for canOpenURL, LSApplicationQueriesSchemes, and radar 179874781 on July 26, 2026; none appears. 

  10. Apple, Describing use of required reason API, Bundle Resources documentation. Source of Apple’s fingerprinting definition quoted here: “Some APIs that your app uses to deliver its core functionality… have the potential of being misused to access device signals to try to identify the device or user, also known as fingerprinting. Regardless of whether a user gives your app permission to track, fingerprinting is not allowed.” Searched July 26, 2026: canOpenURL and LSApplicationQueriesSchemes do not appear on the page, which is the basis for the statement here that Apple never connects the method to fingerprinting. The page describes the reporting requirement and defers the category list to the NSPrivacyAccessedAPIType documentation. The privacy reading of the deprecation in this article is the author’s inference, not Apple’s stated rationale. 

  11. Apple, UIApplication, UIKit class reference. Declared @MainActor class UIApplication, available from iOS 2.0 with no deprecation metadata. Source of the main-actor isolation that open(_:options:completionHandler:) inherits and that canOpenURL(_:) opts out of with nonisolated

  12. Apple, open(_:options:completionHandler:), UIKit instance method reference. Available from iOS 10.0 with no deprecation metadata, declared in both completion-handler and async forms: func open(_ url: URL, options: [UIApplication.OpenExternalURLOptionsKey : Any] = [:], completionHandler completion: (@MainActor @Sendable (Bool) -> Void)? = nil) and func open(_ url: URL, options: [UIApplication.OpenExternalURLOptionsKey : Any] = [:]) async -> Bool. Source of the abstract (“Attempts to asynchronously open the resource at the specified URL”), of the launch behavior quoted here (“If the specified URL scheme is handled by another app, iOS launches that app and passes the URL to it. (Launching the app brings the other app to the foreground.) If no app is capable of handling the specified scheme, the completion handler is called with the success parameter set to false”), and of the instruction that still recommends the deprecated method: “To determine whether an app is installed that is capable of handling the URL, call the canOpenURL(_:) method before calling this one. Be sure to read the description of that method for an important note about registering the schemes you want to employ.” Checked July 26, 2026. 

  13. Apple, Allowing apps and websites to link to your content, Xcode documentation. Source of the server-side association requirement (“When someone installs your app, the system checks a file stored on your web server to verify that your website allows your app to open URLs on its behalf. Only you can store this file on your server, securing the association of your website and your app”), the browser fallback (“If the person hasn’t installed your app, the system opens the URL in their default web browser, allowing your website to handle it”), the note that an app opening its own universal link is not routed to itself (“If your app uses one of the above methods to open a universal link to your website, the link won’t open in your app”), and the same-domain Safari behavior described here. The page lists SwiftUI’s EnvironmentValues.openURL and UIKit’s open(_:options:completionHandler:) among the calls that route universal links. 

  14. Apple, Link, SwiftUI structure reference. Declared @MainActor @preconcurrency struct Link<Label> where Label : View, available from iOS 14.0, macOS 11.0, and watchOS 7.0 with no deprecation metadata. Source of the default behavior quoted here: “When a user taps or clicks a Link, the default behavior depends on the contents of the URL. For example, SwiftUI opens a Universal Link in the associated app if possible, or in the user’s default web browser if not.” 

  15. Apple, OpenURLAction.callAsFunction(_:completion:), SwiftUI instance method reference. Declared @MainActor @preconcurrency func callAsFunction(_ url: URL, completion: @escaping (Bool) -> Void). Source of the completion semantics quoted here: “A closure the method calls after determining if it can open the URL, but possibly before fully opening the URL. The closure takes a Boolean value that indicates whether the method can open the URL.” The sibling callAsFunction(_:) takes a URL alone. Checked July 26, 2026. 

  16. Apple, Build settings reference, Xcode documentation. Searched July 26, 2026 for INFOPLIST_KEY_LSApplicationQueriesSchemes: the setting does not appear, while INFOPLIST_KEY_LSApplicationCategoryType, INFOPLIST_KEY_LSBackgroundOnly, INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace, and INFOPLIST_KEY_LSUIElement do. A build step that merges its own property list can still inject the key, so the absence makes a repository search the right first move rather than a complete audit. 

  17. Apple, Launch Services Keys, Information Property List Key Reference (Apple archive). Source of the key’s definition: “LSApplicationQueriesSchemes (Array - iOS) Specifies the URL schemes you want the app to be able to use with the canOpenURL: method of the UIApplication class. For each URL scheme you want your app to use with the canOpenURL: method, add it as a string in this array.” The page states the key “is supported in iOS 9.0 and later” and mentions no entry ceiling. The archive is the destination of the link inside canOpenURL(_:)’s own discussion. The key has no page in Apple’s current Information Property List reference, verified on July 26, 2026: documentation/bundleresources/information-property-list/lsapplicationqueriesschemes.json returns HTTP 404 while sibling LS* key pages such as lsapplicationcategorytype and lsbackgroundonly return 200. The reference’s own index JSON is not a usable test either way, since it enumerates only seven top-level key groups and names no individual LS* key; lsapplicationcategorytype, which has a live page, is likewise absent from it. 

  18. Apple, OpenURLAction.callAsFunction(_:prefersInApp:), SwiftUI instance method reference. Declared @MainActor @preconcurrency func callAsFunction(_ url: URL, prefersInApp: Bool), available from iOS 26.0, iPadOS 26.0, Mac Catalyst 26.0, macOS 26.0, tvOS 26.0, visionOS 26.0, and watchOS 26.0. Listed on the OpenURLAction page under Instance Methods rather than under Calling the action. It takes a single Boolean rather than an options dictionary, so it is the third and last call signature, and none of the three accepts universalLinksOnly. Checked July 26, 2026. 

  19. Apple, App Store Review Guidelines. Searched July 26, 2026 for LSApplicationQueriesSchemes, canOpenURL, and “25 entries”: zero occurrences of each. Cited to support the absence of a submission rule rather than any affirmative claim. 

관련 게시물

On Demand Resources Is Deprecated: What Background Assets Costs

Apple deprecated ODR in 13 words. The replacement forks three ways, sets an iOS 26 floor, and hands you back the disk ma…

25 분 소요

The iOS 27 Launch Screen Rule: Four Keys or Rejection

Apps built with the iOS 27 SDK must declare a launch screen or the App Store rejects them. The four keys, and how to aud…

16 분 소요