URL Scheme
URL Scheme是app跳转使用的
一般使用情景
App之间跳转
网页跳转App
优点
设计简单、方便
缺点
Schema 无法判断是否安装 App,如果要判断需要JS来判断(判断是否超时)
Schema 被很多 App 禁止
效果
这里写个自定义的URL Scheme、放在备忘录里面
studyoc://www.demo.com?id=1&name=123&age=18
URL Scheme 实现
URL Scheme设置
OC
AppDelegate 关键代码
// 热启动 冷启动 调用
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
// 因为使用了观察者,冷启动的时候,需要等初始化完成
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.50 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSString *hostUrl = url.host;
NSDictionary *paras = [url getURLParameters];
NSLog(@"AppDelegate scheme url = %@",hostUrl);
NSLog(@"AppDelegate scheme 参数 = %@", paras);
LinkModel *model = [LinkModel new];
model.url = hostUrl;
model.para = paras;
[[NSNotificationCenter defaultCenter] postNotificationName:@"Scheme" object:model];
});
return YES;
}
SceneDelegate 关键代码
如果没有使用SceneDelegate,请忽略
// 冷启动调用
- (void)scheme:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions
{
// 冷启动的时候,需要等初始化完成
for (UIOpenURLContext *context in connectionOptions.URLContexts) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.50 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSString *url = context.URL.host;
NSDictionary *paras = [context.URL getURLParameters];
NSLog(@"SceneDelegate scheme url = %@",url);
NSLog(@"SceneDelegate scheme 参数 = %@", paras);
LinkModel *model = [LinkModel new];
model.url = url;
model.para = paras;
[[NSNotificationCenter defaultCenter] postNotificationName:@"Scheme" object:model];
});
}
}
// 热启动调用
- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts
{
NSString *url = URLContexts.allObjects.firstObject.URL.host;
NSDictionary *paras = [URLContexts.allObjects.firstObject.URL getURLParameters];
NSLog(@"SceneDelegate scheme url = %@",url);
NSLog(@"SceneDelegate scheme 参数 = %@", paras);
LinkModel *model = [LinkModel new];
model.url = url;
model.para = paras;
[[NSNotificationCenter defaultCenter] postNotificationName:@"Scheme" object:model];
}
Swift
AppDelegate 关键代码
// 热启动 冷启动 调用
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
// 因为使用了观察者,冷启动的时候,需要等初始化完成
DispatchQueue.main.asyncAfter(deadline: .now()+0.5, execute:{
let hostUrl = url.host
let paras = url.absoluteURL.urlStringtoParams(url.absoluteString)
print("AppDelegate scheme url = (hostUrl)")
print("AppDelegate scheme paras = (paras)")
var model = LinkModel()
var para = Para()
model.url = hostUrl
para.name = paras["name"] as? String
para.id = paras["id"] as? String
para.age = paras["age"] as? String
model.para = para
NotificationCenter.default.post(name: NSNotification.Name.init(rawValue: "Scheme"), object: model)
})
return true
}
SceneDelegate 关键代码
如果没有使用SceneDelegate,请忽略
// 冷启动调用
func scheme(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let _ = (scene as? UIWindowScene) else { return }
for context in connectionOptions.urlContexts{
let hostUrl = context.url.host
let paras = context.url.absoluteURL.urlStringtoParams(context.url.absoluteString)
print("SceneDelegate scheme url = (hostUrl)")
print("SceneDelegate scheme paras = (paras)")
var model = LinkModel()
var para = Para()
model.url = hostUrl
para.name = paras["name"] as? String
para.id = paras["id"] as? String
para.age = paras["age"] as? String
model.para = para
DispatchQueue.main.asyncAfter(deadline: .now()+0.5, execute:
{
NotificationCenter.default.post(name: NSNotification.Name.init(rawValue: "Scheme"), object: model)
})
}
}
// 热启动调用
func scene(_ scene:UIScene, openURLContexts URLContexts:Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url else { return }
let hostUrl = url.host
let paras = url.absoluteURL.urlStringtoParams(url.absoluteString)
print("SceneDelegate scheme url = (hostUrl)")
print("SceneDelegate scheme paras = (paras)")
var model = LinkModel()
var para = Para()
model.url = hostUrl
para.name = paras["name"] as? String
para.id = paras["id"] as? String
para.age = paras["age"] as? String
model.para = para
NotificationCenter.default.post(name: NSNotification.Name.init(rawValue: "Scheme"), object: model)
}
Universal Link
Universal Link是app跳转使用的
一般使用情景
App之间跳转
网页跳转App
优点
直接点击不会出现弹窗、跳转方便
自动判断App有没有安装、跳转到App Store
缺点
配置麻烦 需要SSL证书、测试需要等一段时间
网络不好的情况下、第一次下载成功打开情况下是无法跳转的。原因是Universal Link需要下载apple-app-site-association文件。网络不好会导致下载失败
效果
因为要上传文件给https的服务器、效果图就使用项目的图了
这里写个测试的URL、放在备忘录里面
https://www.demo.com?id=1&name=123&age=18
Universal Link 实现
Universal Link配置
添加Universal Link
编写url
编写apple-app-site-association文件
// appID 格式是teamid.Bundle id
// paths 同意跳转的路径
{
"applinks": {
"apps": [],
"details": [
{
"appID": "teamId.cn.hahn.study.studyOC",
"paths": [ "*" ]
}
]
},
"webcredentials": {
"apps": [ "teamId.cn.hahn.study.studyOC" ]
}
}
teamId查看
将apple-app-site-association文件上传该文件到你的域名所对应的根目录或者.well-known目录
苹果为了方便开发者,提供了一个网页来验证我们编写的这个apple-app-site-association是否合法有效,进入验证网址进行验证:
OC
AppDelegate 关键代码
- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
{
// 因为使用了观察者,冷启动的时候,需要等初始化完成
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.50 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSString *hostUrl = userActivity.webpageURL.host;
NSDictionary *paras = [userActivity.webpageURL getURLParameters];
NSLog(@"AppDelegate universal url = %@",hostUrl);
NSLog(@"AppDelegate universal 参数 = %@", paras);
LinkModel *model = [LinkModel new];
model.url = hostUrl;
model.para = paras;
[[NSNotificationCenter defaultCenter] postNotificationName:@"Universal" object:model];
});
return YES;
return YES;
}
SceneDelegate 关键代码
- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity API_AVAILABLE(ios(13.0))
{
// 处理逻辑
NSString *url = userActivity.webpageURL.host;
NSDictionary *paras = [userActivity.webpageURL getURLParameters];
NSLog(@"SceneDelegate universal url = %@",url);
NSLog(@"SceneDelegate universal 参数 = %@", paras);
LinkModel *model = [LinkModel new];
model.url = url;
model.para = paras;
[[NSNotificationCenter defaultCenter] postNotificationName:@"Universal" object:model];
}
Swift
AppDelegate 关键代码
// 热启动 冷启动 调用
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
// 因为使用了观察者,冷启动的时候,需要等初始化完成
DispatchQueue.main.asyncAfter(deadline: .now()+0.5, execute:{
if let url = userActivity.webpageURL {
let hostUrl = url.host
let paras = url.absoluteURL.urlStringtoParams(url.absoluteString)
print("SceneDelegate universal url = (hostUrl)")
print("SceneDelegate universal paras = (paras)")
var model = LinkModel()
var para = Para()
model.url = hostUrl
para.name = paras["name"] as? String
para.id = paras["id"] as? String
para.age = paras["age"] as? String
model.para = para
NotificationCenter.default.post(name: NSNotification.Name.init(rawValue: "Universal"), object: model)
}
})
return true
}
SceneDelegate 关键代码
// 热启动 冷启动 调用
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
DispatchQueue.main.asyncAfter(deadline: .now()+0.5, execute:{
if let url = userActivity.webpageURL {
let hostUrl = url.host
let paras = url.absoluteURL.urlStringtoParams(url.absoluteString)
print("SceneDelegate universal url = (hostUrl)")
print("SceneDelegate universal paras = (paras)")
var model = LinkModel()
var para = Para()
model.url = hostUrl
para.name = paras["name"] as? String
para.id = paras["id"] as? String
para.age = paras["age"] as? String
model.para = para
NotificationCenter.default.post(name: NSNotification.Name.init(rawValue: "Universal"), object: model)
}
})
}
Deferred Deep Linking
Deferred Deep Linking是延迟深度链接、一般使用Universal Link 或 URL Scheme在没有下载的情况只能跳转到App Store。下载完成以后Universal Link 或 URL Scheme的参数是没有办法调用的,需要重新点击。
Deferred Deep Linking是可以保存Universal Link 或 URL Scheme的参数的技术。一般是是使用第三方的,比如Appflyer等。这些集成大平台的SDK。
有一个取巧的方法,就是在web里面弄一个下载界面。web下载按钮弄一个复制保存参数。App读取粘贴板。