文章

iOS App 之间跳转

iOS App 之间跳转

iOS App 之间跳转有两种方法

  1. URL Scheme
  2. Universal link

URL Scheme

我们可以配置 URL Scheme, 让其他 App 跳转我们的 App. 一般用翻转 BundleID 的方式来保证唯一性,如果一台设备多个 App 使用了同一 Scheme,则先安装的会生效。

配置 URL Scheme

URL Scheme 以 myApp 为例,可以通过两种方法设置.

方法1: Xcode 工程中图形化配置

Target -> Info -> URL Types -> URL Schemes => 输入我们定义的 scheme

方法2: 直接修改 Info.plist 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	//...
	<key>CFBundleURLTypes</key>
	<array>
		<dict>
			<key>CFBundleTypeRole</key>
			<string>Editor</string>
			<key>CFBundleURLSchemes</key>
			<array>
				<string>myApp</string>
			</array>
		</dict>
	</array>
	//...
</dict>
</plist>

设置好后可以在 Safari 浏览器输入 myApp://,若能跳转则表示设置成功。此时设置好了 App 的 Scheme,其它 App 可通过此字符串跳转到我们的 App, 同时如果知道别的 App 的 Scheme 也可以用以下代码跳转到目标 App

1
2
3
4
5
6
7
8
9
10
11
guard let appUrl = URL(string: "myApp://") else { return }

// 直接打开链接
UIApplication.shared.open(appUrl)

// 先判断是否可以打开指定链接, 然后打开
if UIApplication.shared.canOpenURL(appUrl) {
    UIApplication.shared.open(appUrl)
} else {
    print("无法打开")
}

配置白名单

canOpenURL 返回 false 时,并不一定是无法跳转。有以下两种可能:

  • 目标 App 已安装,但未添加进白名单,仍旧可跳转,输出:
1
-canOpenURL: failed for URL: "myApp://" - error: "This app is not allowed to query for scheme otherApp"
  • 目标 App 未安装,则输出:
1
URL: "myApp://" - error: "The operation couldn’t be completed. (OSStatus error -10814.)"

白名单配置方式有两个(最多50个)

方法1: Xcode 项目中可视化配置

Info.plist -> 添加 LSApplicationQueriesSchemes -> 然后一个个添加,如 weixin

方法1: 打开 Info.plist 源码添加下面代码(一些常见 App 白名单)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	//...
	<key>LSApplicationQueriesSchemes</key>
	<array>
		<string>weixin</string>
		<string>mqq</string>
		<string>alipay</string>
		<string>taobao</string>
		<string>pinduoduo</string>
		<string>baiduboxapp</string>
		<string>iosamap</string>
		<string>imeituan</string>
		<string>iqiyi</string>
		<string>tenvideo</string>
		<string>qqmusic</string>
		<string>bilibili</string>
		<string>youku</string>
		<string>dingtalk</string>
		<string>baiduyun</string>
		<string>sinaweibo</string>
		<string>qqmail</string>
		<string>ucbrowser</string>
		<string>eleme</string>
		<string>baidumap</string>
		<string>iting</string>
		<string>diditaxi</string>
		<string>faceu</string>
		<string>wbmain</string>
		<string>vipshop</string>
		<string>tmall</string>
		<string>momochat</string>
		<string>meituanwaimai</string>
		<string>com.baidu.tieba</string>
		<string>baidumusic</string>
		<string>neteasemail</string>
		<string>zhihu</string>
	</array>
	//...
</dict>
</plist>

获取 URL Scheme 跳转时携带的参数.

使用 UIScene

1
2
3
4
5
6
7
8
9
10
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    
    print(URLContexts)
    // [<UIOpenURLContext: 0x60000029e880; URL: myapp://; options: <UISceneOpenURLOptions: 0x60000176eb00; sourceApp: (null); annotation: (null); openInPlace: NO; _eventAttribution: (null)>>]
    
    if let urlCtx = URLContexts.first {
        print(urlCtx.url)
        // myapp://
    }
}

使用 AppDelegate

1
2
3
4
5
6
7
8
9
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    
    let urlString = url.absoluteString
    if urlString.hasPrefix("myapp://") { // url 会被统一为小写
        print("从 myApp:// 进入")
    }
    
    return true
}

THE END.

本文由作者按照 CC BY 4.0 进行授权