iOS开发实战 - 跳转到设置页面的正确姿势(适配iOS11)
前言:
示例:项目里面有扫码功能,当用户第一次扫码—选择不允许访问相机,再次使用扫码APP就需要引导用户到系统的相机页面开启相机权限。类似的功能还有定位、录音、蓝牙、相册等,这些功能都需要给用户提示/引导。
根据上述情况,市场上的App有两种做法:
①不做跳转,给用户提示;
②给用户提示,并做跳转,引导用户到设置界面;


具体看需求吧,亲测过微信(包括定位和相机权限)、QQ、淘宝的(iOS10-iOS11)都没有做跳转,和淘票票一样都是给的提示,不过支付宝的相机权限也做了跳转。
正文:
1.第一次网上查找总结的结果 ❎


可以看到网上大多数的解释是:
①iOS10之前可以进入系统设置的子页面
②iOS10之后不允许跳转到设置的子页面,只允许跳转到设置界面(首页)
说明:上述这种方法我没应用到已上架项目,不过看到有的人通过使用苹果私有API去实现iOS10以后版本能够跳转到系统设置子页面,但同时会加大遇到审核被拒的可能性,所以也不建议大家使用;感兴趣的朋友可以上网查一下相关的代码。
指南2.5.1-性能-软件需求,您的应用程序使用或引用以下非公共的api:LSApplicationWorkspace
准则2.5.1-性能-软件需求
您的应用程序使用或引用以下非公开的api: LSApplicationWorkspace
在App Store中不允许使用非公开的api,因为如果这些api发生变化,就会导致糟糕的用户体验。
下一个步骤
为了解决这个问题,请修改您的应用程序,删除任何非公开的api。如果您在源代码中定义了与上述api相同的方法,我们建议更改您的方法名称,以便它们不再与苹果的私有api发生冲突,以避免您的应用程序在未来的提交中被标记。
另外,如果您正在使用第三方库,请更新这些库的最新版本。如果您没有访问库的源代码,您可以使用“字符串”或“otool”命令行工具搜索已编译的二进制文件。“strings”工具可以输出库调用的方法列表和“otool-ov”将输出objective-a类结构及其定义的方法。这些工具可以帮助您缩小问题代码所在的位置。您还可以使用“nm”工具来验证是否有任何第三方库调用这些api。
思考:参考的其中一篇博客甚至展示了了苹果的文件来证明上述第二点,但现在我再次访问那个博客已经是404了;得到上面的结果让我很不甘心,心想苹果不会这么绝情,于是我就测试了一下其他APP,发现iOS10以后可以跳转到设置界面,看来我没找对答案;于是又搜了一波,终于找到了解决方案。
2. 跳转至系统设置页面的正确姿势(适配 iOS 8.1 ~ iOS10.3.3) ✅
⚠️ 不要在URL Types 中设置prefs 了;
⚠️ 下面两个方法在iOS 11不能实现,本文后面会介绍怎么在iOS11下实现该方案,请耐心看完。
例:跳转到系统设置-相机权限
我是这样写的:
// 亲测版本:iOS 8.1 ~ iOS10.3.3
- (IBAction)pushToSystemConfig:(UIButton *)sender {
NSURL *url = [NSURL URLWithString:@"App-Prefs:root=Privacy&path=CAMERA"];
if ([[UIApplication sharedApplication] canOpenURL:url]){
if (@available(iOS 10.0, *)) {
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
}else {
[[UIApplication sharedApplication] openURL:url];
}
}
}
网上的一种写法,个人觉得稍显麻烦
// 亲测版本:iOS 8.1 ~ iOS10.3.3
- (IBAction)pushToSystemConfig:(UIButton *)sender {
NSString * urlString = @"App-Prefs:root=Privacy&path=CAMERA";
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:urlString]]) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
}else {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[urlString stringByReplacingOccurrencesOfString:@"App-P" withString:@"p"]]];
}
}
补充:
① 当然上述三种方法都可以满足你的需求,但你仔细研究一下发现还是可以简化的;
② iOS 8.1以上版本使用上述方法是有效的,iOS 7 目前没有办法测试(后续补充);
③ iOS 9.0之后版本,应用间进行跳转,在状态栏的左边增加了快速返回上一App的点击事件,方便了不少;
④ 需要注意的是,当你改变了系统相机权限后回到App中,该App会重启;这里还测试了定位功能,而开启定位功能回到应用不会引起应用重启,不过这你也不用担心,这是系统层决定的,你也改变不了什么。
4. 跳转至系统设置页面的正确姿势(适配 iOS 8.1 ~ iOS11.3) ✅
关于iOS11,上面的做法当然行不通了,但还是有办法满足需求的,可以看本文上面的摩拜单车跳转到自己的设置界面的图(现在主流App都是这个做法)
原因:iOS11现在只允许跳转到系统设置首页/该应用的设置界面
// 亲测:iOS 8.1 ~ iOS11.3
// 跳转到设置 - 相机 / 该应用的设置界面
NSURL *url1 = [NSURL URLWithString:@"App-Prefs:root=Privacy&path=CAMERA"];
// iOS10也可以使用url2访问,不过使用url1更好一些,可具体根据业务需求自行选择
NSURL *url2 = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
if (@available(iOS 11.0, *)) {
[[UIApplication sharedApplication] openURL:url2 options:@{} completionHandler:nil];
} else {
if ([[UIApplication sharedApplication] canOpenURL:url1]){
if (@available(iOS 10.0, *)) {
[[UIApplication sharedApplication] openURL:url1 options:@{} completionHandler:nil];
} else {
[[UIApplication sharedApplication] openURL:url1];
}
}
}
3. 如果你不是跳转到系统相机界面,怎么办呢?
其他跳转如下:
注:App-Prefs等同于App-prefs
名称 | 对应字符串 |
---|---|
无线局域网 | App-Prefs:root=WIFI |
蓝牙 | App-Prefs:root=Bluetooth |
蜂窝移动网络 | App-Prefs:root=MOBILE_DATA_SETTINGS_ID |
个人热点 | App-Prefs:root=INTERNET_TETHERING |
运营商 | App-Prefs:root=Carrier |
通知 | App-Prefs:root=NOTIFICATIONS_ID |
通用 | App-Prefs:root=General |
通用-关于本机 | App-Prefs:root=General&path=About |
通用-键盘 | App-Prefs:root=General&path=Keyboard |
通用-辅助功能 | App-Prefs:root=General&path=ACCESSIBILITY |
通用-语言与地区 | App-Prefs:root=General&path=INTERNATIONAL |
通用-还原 | App-Prefs:root=Reset |
墙纸 | App-Prefs:root=Wallpaper |
Siri | App-Prefs:root=SIRI |
隐私 | App-Prefs:root=Privacy |
Safari | App-Prefs:root=SAFARI |
音乐 | App-Prefs:root=MUSIC |
音乐-均衡器 | App-Prefs:root=MUSIC&path=com.apple.Music:EQ |
照片与相机 | App-Prefs:root=Photos |
FaceTime | App-Prefs:root=FACETIME |
如果你发现上面还是没有你需要的字符串怎么办?
找规律:比如我这篇写的进入相机权限页面就没有;将真机/模拟器的语言改为英文,再仔细对比上面的字符串,就会发现规律,多尝试几遍就试出来相应的字符串了。
补充:
名称 | 对应字符串 |
---|---|
个人热点 | App-Prefs:root=INTERNET_TETHERING |
运营商 | App-Prefs:root=Carrier |
隐私->麦克风 | App-Prefs:root=Privacy&path=MICROPHONE |
隐私->定位 | App-Prefs:root=Privacy&path=LOCATION |
隐私->相机 | App-Prefs:root=Privacy&path=CAMERA |