如何将你的Cocoa应用设置为默认的网页浏览器?
我想创建一个应用程序,当用户在其他应用程序中(如Mail、iChat等)点击HTTP或HTTPS链接时,默认启动该应用程序。
如何将你的Cocoa应用设置为默认的网页浏览器?
我想创建一个应用程序,当用户在其他应用程序中(如Mail、iChat等)点击HTTP或HTTPS链接时,默认启动该应用程序。
http://
和https://
的支持,您需要将以下内容添加到应用程序的info.plist文件中。这告诉操作系统您的应用程序能够处理HTTP和HTTPS URL。<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>http URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>http</string>
</array>
</dict>
<dict>
<key>CFBundleURLName</key>
<string>Secure http URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>https</string>
</array>
</dict>
</array>
2) 编写URL处理程序方法
当操作系统想要使用您的应用程序打开URL时,此方法将被调用。无论您向哪个对象添加此方法,都会在下一步中明确传递给事件管理器。URL处理程序方法应该类似于以下内容:
- (void)getUrl:(NSAppleEventDescriptor *)event
withReplyEvent:(NSAppleEventDescriptor *)replyEvent
{
// Get the URL
NSString *urlStr = [[event paramDescriptorForKeyword:keyDirectObject]
stringValue];
//TODO: Your custom URL handling code here
}
3) 注册URL处理程序方法
接下来,告诉事件管理器在使用您的应用程序加载URL时调用哪个对象和方法。在这里的代码中,我将self
作为事件处理程序传递,假设我们从定义getUrl:withReplyEvent:
方法的同一对象中调用setEventHandler
。
您应该在您的应用程序初始化代码的某个地方添加此代码。
NSAppleEventManager *em = [NSAppleEventManager sharedAppleEventManager];
[em
setEventHandler:self
andSelector:@selector(getUrl:withReplyEvent:)
forEventClass:kInternetEventClass
andEventID:kAEGetURL];
一些应用程序,包括早期版本的Adobe AIR,使用替代的WWW!/OURL AppleEvent来请求应用程序打开网址,为了与这些应用程序兼容,您还应该添加以下内容:
[em
setEventHandler:self
andSelector:@selector(getUrl:withReplyEvent:)
forEventClass:'WWW!'
andEventID:'OURL'];
4) 将你的应用设置为默认浏览器
到目前为止,我们已经告诉操作系统你的应用程序是一个浏览器,现在我们需要将其设置为默认浏览器。
我们需要使用启动服务 API 来完成此操作。在这种情况下,我们将我们的应用程序设置为处理 HTTP 和 HTTPS 链接的默认角色处理程序:
CFStringRef bundleID = (CFStringRef)[[NSBundle mainBundle] bundleIdentifier];
OSStatus httpResult = LSSetDefaultHandlerForURLScheme(CFSTR("http"), bundleID);
OSStatus httpsResult = LSSetDefaultHandlerForURLScheme(CFSTR("https"), bundleID);
//TODO: Check httpResult and httpsResult for errors
在更改用户的默认浏览器之前最好征得用户的许可。
自定义 URL 方案
值得注意的是,您也可以使用同样的步骤处理自己的自定义 URL 方案。如果您正在创建一个自定义 URL 方案,建议基于您应用程序的 Bundle Identifier 进行命名,以避免与其他应用程序冲突。因此,如果您的 Bundle ID 是 com.example.MyApp
,您应该考虑使用 x-com-example-myapp://
URLs。
NSString
字面量,然后将其转换为 CFStringRef
,例如 (CFStringRef)@"http"
。相反,直接创建一个 CFString
字面量:CFSTR("http")
。 - Jeremy W. Sherman将此代码复制并粘贴至您的Info.plist文件中
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>Web site URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>http</string>
<string>https</string>
</array>
</dict>
<dict>
<key>CFBundleURLName</key>
<string>http URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>http</string>
</array>
</dict>
<dict>
<key>CFBundleURLName</key>
<string>Secure http URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>https</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>HTML document</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>public.html</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>XHTML document</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>public.xhtml</string>
</array>
</dict>
</array>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeName</key>
<string>GIF image</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.compuserve.gif</string>
</array>
</dict>
<dict>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeName</key>
<string>HTML document</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>public.html</string>
</array>
</dict>
<dict>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeName</key>
<string>XHTML document</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>public.xhtml</string>
</array>
</dict>
<dict>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeName</key>
<string>JavaScript script</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.netscape.javascript-source</string>
</array>
</dict>
<dict>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeName</key>
<string>JPEG image</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>public.jpeg</string>
</array>
</dict>
<dict>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeName</key>
<string>MHTML document</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>org.ietf.mhtml</string>
</array>
</dict>
<dict>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeName</key>
<string>HTML5 Audio (Ogg)</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>org.xiph.ogg-audio</string>
</array>
</dict>
<dict>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeName</key>
<string>HTML5 Video (Ogg)</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>org.xiph.ogv</string>
</array>
</dict>
<dict>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeName</key>
<string>PNG image</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>public.png</string>
</array>
</dict>
<dict>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeName</key>
<string>SVG document</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>public.svg-image</string>
</array>
</dict>
<dict>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeName</key>
<string>Plain text document</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>public.text</string>
</array>
</dict>
<dict>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeName</key>
<string>HTML5 Video (WebM)</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>org.webmproject.webm</string>
</array>
</dict>
<dict>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeName</key>
<string>WebP image</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>org.webmproject.webp</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>org.chromium.extension</string>
</array>
</dict>
<dict>
<key>CFBundleTypeIconFile</key>
<string>document.icns</string>
<key>CFBundleTypeName</key>
<string>PDF Document</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.adobe.pdf</string>
</array>
</dict>
</array>
您的应用将会显示在系统偏好设置中,并成为默认浏览器
func application(_ application: NSApplication, open urls: [URL]) {
// do a for loop, I recommend it
}
如果您只想更改http(s)的默认助手应用程序,可以在Safari首选项中进行更改。在那里,您将找到一个下拉菜单,可以让您选择所有已注册的http处理程序应用程序。要自动将应用程序设置为默认浏览器,请参阅先前的说明。
13.0
更新默认浏览器现在出现在:
系统偏好设置 > 桌面与 Dock > 默认 Web 浏览器
info.plist保持不变,为了完整起见,再次将其粘贴在此处。一些答案建议向该文件添加更多条目,但这并不是真正必要的,这是更精简和最低要求的选项。
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeIconSystemGenerated</key>
<integer>1</integer>
<key>CFBundleTypeName</key>
<string>HTML document</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Default</string>
<key>LSItemContentTypes</key>
<array>
<string>public.html</string>
</array>
</dict>
<dict>
<key>CFBundleTypeIconSystemGenerated</key>
<integer>1</integer>
<key>CFBundleTypeName</key>
<string>XHTML document</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Default</string>
<key>LSItemContentTypes</key>
<array>
<string>public.xhtml</string>
</array>
</dict>
</array>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>Website URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>http</string>
<string>https</string>
</array>
</dict>
</array>
<key>NSUserActivityTypes</key>
<array>
<string>NSUserActivityTypeBrowsingWeb</string>
</array>
LSSetDefaultHandlerForURLScheme
已被弃用,现在我们可以使用NSWorkspace
的功能,支持完成处理程序和async/await
。
setDefaultApplication(at:toOpenURLsWithScheme:completion:)
func setDefaultApplication(at applicationURL: URL, toOpenURLsWithScheme urlScheme: String) async throws
try? await NSWorkspace.shared.setDefaultApplication(
at: Bundle.main.bundleURL,
toOpenURLsWithScheme: "http")
现在系统提示用户确认更改默认浏览器,这是一个很大的改进。
我发现只使用http
协议就足够了,就像上面的例子一样。尝试使用https
会抛出错误。
为了出现在系统偏好设置 > 通用 > 默认网页浏览器
选项中(至少适用于macOS 11),您需要将HTML和XHTML文档类型添加到Info.plist中(在已经描述的4个步骤之后,如接受的答案所述),就像这样:
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>HTML document</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>public.html</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>XHTML document</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>public.xhtml</string>
</array>
</dict>
</array>