1、Xcode 项目属性
- Product Name
- 软件名称、产品名称、项目名称
- Organization Name
- 公司名称、组织名称
- Organization Identifier
- 公司的唯一标识
- 一般是公司域名的反写,比如 com.baidu
- Bundle Identifier
- 软件的唯一标识
- 一般是 Organization Identifier + Product Name
2、App 应用间跳转
2.1 应用跳转原理
相信从一个应用跳转到另一个应用大家并不陌生,最常见的莫过于第三方登录,支付宝支付等等。这些东西大家都耳熟能详,集成进来也很简单,跟着第三方 sdk 集成文档一步步走下来就是了,通常 sdk 集成文档都需要你在工程中配置一堆堆的东西,但是配置的这些东西,你真的明白了吗?比如下面这个,第三方登录或分享需要你配置的 URL Schemes:
1、一些概念的补充
- 协议:双方互相遵守的一种规范,只有遵守共同的协议规范才能进行彼此的通信。比如我们最熟悉的网络协议 http 协议。
- URL:资源的路径或地址。在 iOS 中有一个专门用于包装资源路径的类 NSURL。
一个完整 URL 的组成
例如:http://123.0.0.1/path?page=100 http:// :协议类型 123.0.0.1 :服务器 ip 地址 /path :资源存放的是路径 page=100 :请求的参数
NSURL 包装一个完整地址
NSURL *url = [NSURL URLWithString:@"http://123.0.0.1/path?page=100"]; NSLog(@"scheme(协议):%@",url.scheme); NSLog(@"host(域名):%@",url.host); NSLog(@"path(路径):%@",url.path); NSLog(@"query(参数):%@",url.query);
打印结果如下
2015-12-02 14:50:38.442 TestDemo[5632:406869] scheme(协议):http 2015-12-02 14:50:38.442 TestDemo[5632:406869] host(域名):123.0.0.1 2015-12-02 14:50:38.442 TestDemo[5632:406869] path(路径):/path 2015-12-02 14:50:38.442 TestDemo[5632:406869] query(参数):page=100
2、跳转的原理
一个应用能打开另一个应用的必然条件是,另一个应用必须配置一个 scheme(协议),这样应用程序才能根据协议找到需要打开的应用。
在 iOS 中,从一个 app 打开另一个 app,这必然牵扯到两个 app 之间的交互和通信,像这种涉及到整个应用程序层面的事情,苹果有一个专门的类来管理 UIApplication。在 iOS 中 UIApplication 其实就是代表着应用程序,这点从它的命名就可以窥之。而我们要打开另一个应用程序,其实就是 UIApplication 下面这个的 API。
iOS 系统版本 < 10.0
通过应用程序打开一个资源路径 @param url 资源路径的地址 @return 返回成功失败的信息 - (BOOL)openURL:(NSURL*)url;
iOS 系统版本 >= 10.0
通过应用程序打开一个资源路径 @param url 资源路径的地址 @param options 附加参数 @param completion 完成回调 - (void)openURL:(NSURL*)url options:(NSDictionary
*)options completionHandler:(void (^ __nullable)(BOOL success))completion; - UIApplication 的头文件中列了一个可用在 options 字典中的 key: UIApplicationOpenURLOptionUniversalLinksOnly,可以设置布尔值(默认是 NO),如果设置为 YES,则只能打开应用里配置好的有效通用链接。如果应用程序没有配置,或者用于禁止打开这个链接,则 completion handler 回调里的success 为 NO。
它的一些我们非常熟悉的用法
// 拨打系统电话 NSURL *url = [NSURL URLWithString:@"tel://10086"]; [[UIApplication sharedApplication] openURL:url]; // 发送系统短信 NSURL *url = [NSURL URLWithString:@"sms://1383838438"]; [[UIApplication sharedApplication] openURL:url];
拨打系统电话、发送系统短信其实就是应用间的跳转。只要一执行以上两个方法就会从你当前的应用跳转到系统的拨打电话界面、发送短信界面,拨打系统电话、发送短信它俩就是手机本身自带的两个 app 应用。上面打电话和发短信的实现代码大同小异,唯一的区别是传递的 NSURL 参数不一样,导致他们跳转到不同的应用场景。我们再仔细分析下传给它们的 NSURL 参数,就会发现 NSURL 的 scheme(协议)不一样,打电话是 “tel://” 协议,发短信是 “sms://” 协议。
2.2 实现两个 App 间的跳转
由 App:AppJump1 跳转到 App:AppJump2。
1、配置协议:在被跳转的 App(如 AppJump2)的 TARGETS => Info => URL Types => URL Scheme 配置一个协议 scheme,这里命名为 app2(名字可随意配置,当然最好是英文并且跟你项目相关)
2、配置协议白名单:在 iOS9.0 + 系统隐私控制里禁止查询设备中已安装的 App,所以在 iOS9.0 + 系统中要实现应用间跳转还需要配置协议白名单。在发起跳转的 App(如 AppJump1)的 Info.plist 文件中增加一个 LSApplicationQueriesSchemes 字段,把它设置为数组类型,并配置需要跳转的协议名单。
3、在发起跳转的 App(如 AppJump1)的执行跳转方法中实现下面方法。
// app2 为在 App2 中设置的协议 scheme NSURL *url = [NSURL URLWithString:@"app2://"]; // 判断能否跳转到 App2 if ([[UIApplication sharedApplication] canOpenURL:url]) { // 跳转到 App2 [[UIApplication sharedApplication] openURL:url]; } else { NSLog(@"没有安装应用"); }
2.3 跳转到指定界面
想要跳转到指定界面,必然是上一个 App 告诉下一个 App(被跳转的 App)需要跳转到哪个界面,而如何告诉它这里便涉及到两个 App 的通信。我们从上面可以知道,两个 App 之间的跳转只需要配置一个 scheme,然后通过 UIApplication 调用它的对象方法 openURL: 即可实现,除此之外再也没有实现任何代码了。而这之间是如何通信的呢?答案依然是协议。
1、在 "app2://" 协议后面的域名加上一些字段用来标记需要跳转的界面。
// 进入更多界面 // app2 为在 App2 中设置的协议 scheme NSURL *url = [NSURL URLWithString:@"app2://more"]; // 判断能否跳转到 App2 if ([[UIApplication sharedApplication] canOpenURL:url]) { // 跳转到 App2 [[UIApplication sharedApplication] openURL:url]; } else { NSLog(@"没有安装应用"); } // 进入设置界面 // app2 为在 App2 中设置的协议 scheme NSURL *url = [NSURL URLWithString:@"app2://set"]; // 判断能否跳转到 App2 if ([[UIApplication sharedApplication] canOpenURL:url]) { // 跳转到 App2 [[UIApplication sharedApplication] openURL:url]; } else { NSLog(@"没有安装应用"); }
2、来到被跳转的应用的 AppDelegate.m 文件中,监听其代理方法
application: handleOpenURL:
,当应用程序将要被其他程序打开时,会先执行此方法,并传递 url 过来。在 iOS9.0 + 上面的方法被废弃了,改用这个方法application: openURL: options:
// NS_DEPRECATED_IOS(2_0, 9_0) - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url { if ([url.host isEqualToString:@"more"]) { // 到此做界面的跳转,进入更多界面 } if ([url.host isEqualToString:@"set"]) { // 到此做界面的跳转,进入设置界面 } return YES; } // NS_AVAILABLE_IOS(9_0) - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary
*)options { if ([url.host isEqualToString:@"more"]) { // 到此做界面的跳转,进入更多界面 } if ([url.host isEqualToString:@"set"]) { // 到此做界面的跳转,进入设置界面 } return YES; }
2.4 常用 App 的跳转
在 iOS9.0 + 系统隐私控制里禁止查询设备中已安装的 App,所以在 iOS9.0 + 系统中要实现应用间跳转还需要配置协议白名单。在发起跳转的 App 的 Info.plist 文件中增加一个 LSApplicationQueriesSchemes 字段,把它设置为数组类型,并配置需要跳转的协议名单。
// 发送系统短信 NSURL *url = [NSURL URLWithString:@"sms://1383838438"]; [[UIApplication sharedApplication] openURL:url];
常用 App 相应的 URL 地址
URL 地址: tel://电话号码 // 打电话 sms://电话号码 // 发短信 mailto://邮件地址 // 发邮件 http://网址 // 调用浏览器 Safari https://网址 // 调用浏览器 Safari // 微信 weixin:// wechat:// // QQ mqq:// mqqapi:// mqqOpensdkSSoLogin:// mqqopensdkapiV2:// mqqopensdkapiV3:// wtloginmqq2:// // 新浪微博 sinaweibo:// sinaweibohd:// sinaweibosso:// sinaweibohdsso:// weibosdk:// weibosdk2.5:// // 支付宝 alipay:// alipayshare://
2.5 系统设置界面的跳转
设置跳转有三种方式,每一种的使用场景都不同。 并且你在跳转到系统中自己应用下面设置的时候,你的应用要提前至少申请了某一个权限,如通知,定位等,否则,会引起崩溃。
- 方式一:prefs:root=某项服务
- iOS 系统版本 < iOS10 , 只能跳转到系统设置页面。
- 在 iOS10 系统上,不会跳转。
- 方式二:prefs:root=bundleID
- iOS8 <= iOS 系统版本 < iOS10,支持跳转到第三方应用的设置界面中。
- 在 iOS7 系统上,仅仅只是跳转到设置应用,不推荐使用。
- 在 iOS10 系统上,不会跳转。
- 方式三:UIApplicationOpenSettingsURLString
- iOS8 <= iOS 系统版本 < iOS10,支持跳转到系统设置。
- 在 iOS10 系统上,支持跳转到自己应用设置,不支持跳转到系统设置。
- 方式一:prefs:root=某项服务
1、在 iOS6 以下系统中。
// 打开蓝牙设置界面 NSURL *url = [NSURL URLWithString:@"prefs:root=Bluetooth"]; [[UIApplication sharedApplication] openURL:url];
2、在 iOS6 至 iOS9 系统中,必须在 URL Types 中添加 prefs 才能打开相应的设置界面。
// 打开蓝牙设置界面 NSURL *url = [NSURL URLWithString:@"prefs:root=Bluetooth"]; [[UIApplication sharedApplication] openURL:url]; // 打开第三方应用设置界面,bundleID 为第三方应用的唯一标识,iOS8 iOS9 可用 NSURL *url = [NSURL URLWithString:@"prefs:root=bundleID"]; [[UIApplication sharedApplication] openURL:url];
3、在 iOS10 系统中苹果已经不允许 app 跳到各个系统设置页面了,只能跳转到自己应用设置页面。
// 打开自己应用设置界面 NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString]; [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
将 prefs:root=某项服务 改为 app-Prefs:root=某项服务 也可以成功跳转到系统设置页面。
// 打开蓝牙设置界面 NSURL *url = [NSURL URLWithString:@"app-Prefs:root=Bluetooth"]; [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
系统设置 相应的 URL 地址
URL 地址: UIApplicationOpenSettingsURLString // 系统设置,支持 iOS8, iOS9, iOS10 系统 prefs:root=General&path=About // 关于本机 prefs:root=General&path=ACCESSIBILITY // 辅助功能 prefs:root=AIRPLANE_MODE prefs:root=General&path=AUTOLOCK prefs:root=General&path=USAGE/CELLULAR_USAGE prefs:root=Brightness prefs:root=Bluetooth // 蓝牙设置 prefs:root=General&path=DATE_AND_TIME prefs:root=DISPLAY&BRIGHTNESS // 显示与亮度 prefs:root=FACETIME prefs:root=General // 通用设置 prefs:root=General&path=Keyboard prefs:root=CASTLE prefs:root=CASTLE&path=STORAGE_AND_BACKUP prefs:root=General&path=INTERNATIONAL prefs:root=LOCATION_SERVICES // 定位设置 prefs:root=ACCOUNT_SETTINGS prefs:root=MOBILE_DATA_SETTINGS_ID // 蜂窝网路 prefs:root=MUSIC // 音乐 prefs:root=MUSIC&path=EQ prefs:root=MUSIC&path=VolumeLimit prefs:root=General&path=Network prefs:root=NIKE_PLUS_IPOD prefs:root=NOTES // Notes prefs:root=NOTIFICATIONS_ID // 系统通知 prefs:root=Phone prefs:root=Photos // 照片与相机 prefs:root=Privacy // 隐私设置 prefs:root=General&path=ManagedConfigurationList prefs:root=General&path=Reset prefs:root=Sounds&path=Ringtone prefs:root=Safari // Safari prefs:root=General&path=Assistant prefs:root=Set // 系统设置 prefs:root=Sounds // 声音设置 prefs:root=General&path=SOFTWARE_UPDATE_LINK prefs:root=STORE // APP Store prefs:root=TWITTER prefs:root=FACEBOOK prefs:root=General&path=USAGE prefs:root=VIDEO prefs:root=General&path=Network/VPN prefs:root=Wallpaper // 壁纸设置 prefs:root=WIFI // Wifi 设置 prefs:root=INTERNET_TETHERING // 个人热点
3、代码退出程序设置
- (IBAction)outClick:(id)sender { // 创建退出动画 [UIView beginAnimations:@"exitApplication" context:nil]; [UIView setAnimationDuration:0.5]; [UIView setAnimationDelegate:self]; [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view.window cache:NO]; [UIView setAnimationDidStopSelector:@selector(animationFinished:finished:context:)]; self.view.window.bounds = CGRectMake(0, 0, 0, 0); [UIView commitAnimations]; } // 动画完成后的响应事件 - (void)animationFinished:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { if ([animationID compare:@"exitApplication"] == 0) { // 退出 App exit(0); } }
4、App 间的通信方式
- 具体讲解见
5、App 与外设间的通信方式
- 具体讲解见