更新了Xcode8 以及 iOS10,App访问用户的相机、相册、麦克风、通讯录的权限都需要重新进行相关的配置,不然在Xcode8中打开编译的话会直接crash.
需要在info.plist中添加App需要的一些设备权限。
相机NSCameraUsageDescription
相册NSPhotoLibraryUsageDescription
通讯录NSContactsUsageDescription
始终访问位置NSLocationAlwaysUsageDescription
位置NSLocationUsageDescription
在使用期间访问位置NSLocationWhenInUseUsageDescription
麦克风NSMicrophoneUsageDescription
访问蓝牙NSBluetoothPeripheralUsageDescription
访问日历NSCalendarsUsageDescription
访问媒体资料库NSAppleMusicUsageDescription
访问健康分享NSHealthShareUsageDescription
访问健康更新NSHealthUpdateUsageDescription
访问运动与健身NSMotionUsageDescription
访问提醒事项NSRemindersUsageDescription
提别提醒: 从2017年1月1日起,强制使用https,所有新提交的 app 默认不允许使用NSAllowsArbitraryLoads来绕过ATS的限制 安全传输不再支持SSLv3, 建议尽快停用SHA1和3DES算法.
iOS10相册相机闪退bug
http://www.jianshu.com/p/5085430b029f
iOS 10 因苹果健康导致闪退 crash
http://www.jianshu.com/p/545bd1bf5a23
麦克风、多媒体、地图、通讯录
ios10相机等崩溃
http://www.jianshu.com/p/ec15dadd38f3
iOS10 配置须知
http://www.jianshu.com/p/65f21dc5c556
iOS开发 适配iOS10以及Xcode8
http://www.jianshu.com/p/9756992a35ca
iOS 10 的适配问题
http://www.jianshu.com/p/f8151d556930
兼容iOS10资料整理笔记
http://www.jianshu.com/p/0cc7aad638d9?from=groupmessage&isappinstalled=0
下面贴出来错误:
Q1: iOS10相册相机闪退问题:
iOS10系统下调用系统相册、相机功能,遇到闪退的情况,日志描述如下:
This app has crashed because it attempted to access privacy-sensitive data without a usage description.The app’s Info.plist must contain an NSPhotoLibraryUsageDescription key with a string value explaining to the user how the app uses this data.
解决方法:在info.plist文件下添加
相机权限
NSCameraUsageDescription
cameraDesciption
相册权限
NSPhotoLibraryUsageDescription
photoLibraryDesciption
Q2: iOS 10 因苹果健康导致闪退
如果在app中调用了苹果健康,iOS10中会出现闪退。控制台报出的原因是:Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘NSHealthUpdateUsageDescription must be set in the app’s Info.plist in order to request write authorization.’
这是因为我们要在info.plist文件中声明苹果健康的使用权限,所以在info.plist中添加以下key就可以:
请求写入
NSHealthUpdateUsageDescription
some string value stating the reason
请求读取
NSHealthShareUsageDescription
some string value stating the reasonPaste_Image.png
Q3: Xcode 打印的那些杂乱无章的bug
更新Xcode8之后,新建立工程,都会打印一堆莫名其妙看不懂的Log.比如如这些
subsystem: com.apple.UIKit, category: HIDEventFiltered, enable_level:0, persist_level:0, default_ttl:0, info_ttl:0, debug_ttl:0, generate_symptoms:0, enable_oversize:1,
屏蔽的方法如下:
Xcode8里边 Edit Scheme->Run-> Arguments, 在Environment Variables里边添加
OS_ACTIVITY_MODE = Disable 就行
Q4:IOS10的GoogleMap问题
错位信息:
This app is not allowed to query for scheme comgooglemaps
You must add a key to your info.plist for this to work.
<key>LSApplicationQueriesSchemes</key> <array> <string>comgooglemaps</string> </array>
Q5:Xcode的错误信息如下:
[access] This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSCalendarsUsageDescription key with a string value explaining to the user how the app uses this data.
解决方法:
1,在项目中找到info.plist文件,右击有个 Open As,以Source Code 的形式打开
2,分别复制 以下 Value 和Key,Key 一定不能错,Value 貌似可以随便填写
<!-- 相册 -->
<key>NSPhotoLibraryUsageDescription</key>
<string>App需要您的同意,才能访问相册</string>
<!-- 相机 -->
<key>NSCameraUsageDescription</key>
<string>App需要您的同意,才能访问相机</string>
<!-- 麦克风 -->
<key>NSMicrophoneUsageDescription</key>
<string>App需要您的同意,才能访问麦克风</string>
<!-- 位置 -->
<key>NSLocationUsageDescription</key>
<string>App需要您的同意,才能访问位置</string>
<!-- 在使用期间访问位置 -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>App需要您的同意,才能在使用期间访问位置</string>
<!-- 始终访问位置 -->
<key>NSLocationAlwaysUsageDescription</key>
<string>App需要您的同意,才能始终访问位置</string>
<!-- 日历 -->
<key>NSCalendarsUsageDescription</key>
<string>App需要您的同意,才能访问日历</string>
<!-- 提醒事项 -->
<key>NSRemindersUsageDescription</key>
<string>App需要您的同意,才能访问提醒事项</string>
<!-- 运动与健身 -->
<key>NSMotionUsageDescription</key> <string>App需要您的同意,才能访问运动与健身</string>
<!-- 健康更新 -->
<key>NSHealthUpdateUsageDescription</key>
<string>App需要您的同意,才能访问健康更新 </string>
<!-- 健康分享 -->
<key>NSHealthShareUsageDescription</key>
<string>App需要您的同意,才能访问健康分享</string>
<!-- 蓝牙 -->
<key>NSBluetoothPeripheralUsageDescription</key>
<string>App需要您的同意,才能访问蓝牙</string>
<!-- 媒体资料库 -->
<key>NSAppleMusicUsageDescription</key>
<string>App需要您的同意,才能访问媒体资料库</string>
eg:其他权限描述,debug 控制台都会有输出的,自行添加就OK
Q6:UIStatusBar方法过期:
解决办法(fix method):
//属性&&方法
@property(nonatomic, readonly) UIStatusBarStyle preferredStatusBarStyle NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; // Defaults to UIStatusBarStyleDefault
@property(nonatomic, readonly) BOOL prefersStatusBarHidden NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; // Defaults to NO
- (UIStatusBarStyle)preferredStatusBarStyle NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; // Defaults to UIStatusBarStyleDefault
- (BOOL)prefersStatusBarHidden NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; // Defaults to NO
// Override to return the type of animation that should be used for status bar changes for this view controller. This currently only affects changes to prefersStatusBarHidden.- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; // Defaults to UIStatusBarAnimationFade
//可以这样写
- (UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleDefault;
}
Q7:Label中的文字显示不全
用Xcode 8和Xcode 7.3
分别测试了下,如下图:
Xcode 8
Xcode 7
创建一个Label然后让它自适应大小,字体大小都是17最后输出的宽度是不一样的,我们再看一下,下面的数据就知道为什么升iOS 10之后App中有的文字显示不全了:
发现英文字母没有问题,只有汉字有问题。目前只有一个一个修改控件解决这个问题。
解决办法(fix method):
UILabel *myLabel = [UILabel new];
/*UIFont 的preferredFontForTextStyle: 意思是指定一个样式,并让字体大小符合用户设定的字体大小。 */
myLabel.font =[UIFont preferredFontForTextStyle: UIFontTextStyleHeadline];
/*
Indicates whether the corresponding element should automatically update its font when the device’s UIContentSizeCategory is changed.
For this property to take effect, the element’s font must be a font vended using +preferredFontForTextStyle: or +preferredFontForTextStyle:compatibleWithTraitCollection: with a valid UIFontTextStyle.
*/
//是否更新字体的变化
myLabel.adjustsFontForContentSizeCategory = YES;
Q8:使用Xib awakeFromNib的警告问题
在Xcode 8之前我们使用Xib初始化- (void)awakeFromNib {}都是这么写也没什么问题,但是在Xcode 8会有如下警告:
如果不喜欢这个警告的话,应该明确的加上[super awakeFromNib];
Q9:判断系统版本
oc
//值为10.0
[[UIDevice currentDevice] systemVersion]
if ([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){.majorVersion = 9, .minorVersion = 1, .patchVersion = 0}]) {
NSLog(@"Hello from > iOS 9.1");
}
if ([NSProcessInfo.processInfo isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){9,3,0}]) {
NSLog(@"Hello from > iOS 9.3");
}
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_9_0) {
// do stuff for iOS 9 and newer
}
else {
// do stuff for older versions than iOS 9
}
swift
if NSProcessInfo().isOperatingSystemAtLeastVersion(NSOperatingSystemVersion(majorVersion: 10, minorVersion: 0, patchVersion: 0)) {
// 代码块
}
if #available(iOS 10.0, *) {
// 代码块
} else {
// 代码块
}
Q10 :ATS的问题
iOS 9中默认非HTTPS的网络是被禁止的,当然我们也可以把NSAllowsArbitraryLoads设置为YES禁用ATS。不过iOS 10从2017年1月1日起苹果不允许我们通过这个方法跳过ATS
,也就是说强制我们用HTTPS,如果不这样的话提交App可能会被拒绝。但是我们可以通过NSExceptionDomains来针对特定的域名开放HTTP可以容易通过审核。
Q11:Xib文件的注意事项
使用Xcode8打开xib文件后,会出现下图的提示:
大家选择Choose Device即可。
之后大家会发现布局啊,frame乱了,只需要更新一下frame即可。如下图
注意:如果按上面的步骤操作后,在用Xcode7打开Xib会报一下错误,
解决办法:右键Xib文件->Open As Source Code 删除下面的
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
这句话,以及把< document >中的toolsVersion和< plugIn >中的version改成你正常的xib文件中的值,不过不建议这么做,在Xcode8出来后,希望大家都快速上手,全员更新。
Q12:tabbar隐藏上面的黑线
//UITabBarController里面
[[UITabBar appearance] setBackgroundImage:[UIImage imageNamed:@"BarBackground.png"];
[[UITabBar appearance] setShadowImage:[UIImage new]];
ios10的一些改动如下
1.UIColor 新增方法
在iOS 10 苹果官方建议我们使用sRGB,因为它性能更好,色彩更丰富。如果你自己为UIColor写了一套分类的话也可尝试替换为sRGB,UIColor类中新增了两个Api如下:
+ (UIColor *)colorWithDisplayP3Red:(CGFloat)displayP3Red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha NS_AVAILABLE_IOS(10_0);
- (UIColor *)initWithDisplayP3Red:(CGFloat)displayP3Red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha NS_AVAILABLE_IOS(10_0);
2.真彩色的显示
真彩色的显示会根据光感应器来自动的调节达到特定环境下显示与性能的平衡效果,如果需要这个功能的话,可以在info.plist-Source Code里配置:
<key>UIWhitePointAdaptivityStyle</key>
它有五种取值,分别是:
<string>UIWhitePointAdaptivityStyleStandard</string> // 标准模式
<string>UIWhitePointAdaptivityStyleReading</string> // 阅读模式
<string>UIWhitePointAdaptivityStylePhoto</string> // 图片模式
<string>UIWhitePointAdaptivityStyleVideo</string> // 视频模式
<string>UIWhitePointAdaptivityStyleStandard</string> // 游戏模式
也就是说如果你的项目是阅读类的,就选择UIWhitePointAdaptivityStyleReading这个模式,五种模式的显示效果是从上往下递减,也就是说如果你的项目是图片处理类的,你选择的是阅读模式,给选择太好的效果会影响性能.
3.UITextContentType
// The textContentType property is to provide the keyboard with extra information about the semantic intent of the text document.
@property(nonatomic,copy) UITextContentType textContentType NS_AVAILABLE_IOS(10_0); // default is nil
在iOS 10UITextField添加了textContentType枚举,指示文本输入区域所期望的语义意义。
使用此属性可以给键盘和系统信息,关于用户输入的内容的预期的语义意义。例如,您可以指定一个文本字段,用户填写收到一封电子邮件确认uitextcontenttypeemailaddress。当您提供有关您期望用户在文本输入区域中输入的内容的信息时,系统可以在某些情况下自动选择适当的键盘,并提高键盘修正和主动与其他文本输入机会的整合。
4. UIRefreshControl的使用
在iOS 10 中, UIRefreshControl可以直接在UICollectionView和UITableView中使用,并且脱离了UITableViewController.现在RefreshControl是UIScrollView的一个属性.使用方法:
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(loadData) forControlEvents:UIControlEventValueChanged];
collectionView.refreshControl = refreshControl;
5.Notification(通知)
自从Notification被引入之后,苹果就不断的更新优化,但这些更新优化只是小打小闹,直至现在iOS 10开始真正的进行大改重构,这让开发者也体会到UserNotifications的易用,功能也变得非常强大。
参考博文:IOS-iOS10 推送通知适配
http://blog.csdn.net/Maxdong24/article/details/53219175
iOS 9 以前的通知
在调用方法时,有些方法让人很难区分,容易写错方法,这让开发者有时候很苦恼。
应用在运行时和非运行时捕获通知的路径还不一致。
应用在前台时,是无法直接显示远程通知,还需要进一步处理。
已经发出的通知是不能更新的,内容发出时是不能改变的,并且只有简单文本展示方式,扩展性根本不是很好。
iOS 10 开始的通知
所有相关通知被统一到了UserNotifications.framework框架中。
增加了撤销、更新、中途还可以修改通知的内容。
通知不在是简单的文本了,可以加入视频、图片,自定义通知的展示等等。
iOS 10相对之前的通知来说更加好用易于管理,并且进行了大规模优化,对于开发者来说是一件好事。
iOS 10开始对于权限问题进行了优化,申请权限就比较简单了(本地与远程通知集成在一个方法中)。
iOS 10 通知学习相关资料:
UserNotifications: 苹果官方文档
苹果官方视频1
苹果官方视频2
苹果官方视频3
活久见的重构 - iOS 10 UserNotifications 框架解析
WWDC2016 Session笔记 - iOS 10 推送Notification新特性
6.UICollectionViewCell
在iOS 10 之前,UICollectionView上面如果有大量cell,当用户活动很快的时候,整个UICollectionView的卡顿会很明显,为什么会造成这样的问题,这里涉及到了iOS 系统的重用机制,当cell准备加载进屏幕的时候,整个cell都已经加载完成,等待在屏幕外面了,也就是整整一行cell都已经加载完毕,这就是造成卡顿的主要原因,专业术语叫做:掉帧.要想让用户感觉不到卡顿,我们的app必须帧率达到60帧/秒,也就是说每帧16毫秒要刷新一次.
iOS 10 之前UICollectionViewCell的生命周期是这样的:
用户滑动屏幕,屏幕外有一个cell准备加载进来,把cell从reusr队列拿出来,然后调用prepareForReuse方法,在这个方法里面,可以重置cell的状态,加载新的数据;
继续滑动,就会调用cellForItemAtIndexPath方法,在这个方法里面给cell赋值模型,然后返回给系统;
当cell马上进去屏幕的时候,就会调用willDisplayCell方法,在这个方法里面我们还可以修改cell,为进入屏幕做最后的准备工作;
执行完willDisplayCell方法后,cell就进去屏幕了.当cell完全离开屏幕以后,会调用didEndDisplayingCell方法.
iOS 10 UICollectionViewCell的生命周期是这样的:
用户滑动屏幕,屏幕外有一个cell准备加载进来,把cell从reusr队列拿出来,然后调用prepareForReuse方法,在这里当cell还没有进去屏幕的时候,就已经提前调用这个方法了,对比之前的区别是之前是cell的上边缘马上进去屏幕的时候就会调用该方法,而iOS 10 提前到cell还在屏幕外面的时候就调用;
在cellForItemAtIndexPath中创建cell,填充数据,刷新状态等操作,相比于之前也提前了;
用户继续滑动的话,当cell马上就需要显示的时候我们再调用willDisplayCell方法,原则就是:何时需要显示,何时再去调用willDisplayCell方法;
当cell完全离开屏幕以后,会调用didEndDisplayingCell
方法,跟之前一样,cell会进入重用队列.在iOS 10 之前,cell只能从重用队列里面取出,再走一遍生命周期,并调用cellForItemAtIndexPath
创建或者生成一个cell.在iOS 10 中,系统会cell保存一段时间,也就是说当用户把cell滑出屏幕以后,如果又滑动回来,cell不用再走一遍生命周期了,只需要调用willDisplayCell
方法就可以重新出现在屏幕中了.iOS 10 中,系统是一个一个加载cell的,二以前是一行一行加载的,这样就可以提升很多性能;
iOS 10 新增加的Pre-Fetching预加载
这个是为了降低UICollectionViewCell在加载的时候所花费的时间,在 iOS 10 中,除了数据源协议和代理协议外,新增加了一个UICollectionViewDataSourcePrefetching
协议,这个协议里面定义了两个方法:
- (void)collectionView:(UICollectionView *)collectionView prefetchItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths NS_AVAILABLE_IOS(10_0);
- (void)collectionView:(UICollectionView *)collectionView cancelPrefetchingForItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths NS_AVAILABLE_IOS(10_0);
在ColletionView prefetchItemsAt indexPaths这个方法是异步预加载数据的,当中的indexPaths数组是有序的,就是item接收数据的顺序;CollectionView cancelPrefetcingForItemsAt indexPaths这个方法是可选的,可以用来处理在滑动中取消或者降低提前加载数据的优先级.注意:这个协议并不能代替之前读取数据的方法,仅仅是辅助加载数据.Pre-Fetching预加载对UITableViewCell同样适用.
7.UINavigationBar
iOS10之前的navigationBar的背景是@”_UINavigationBarBackground”,到iOS10变成了@”_UIBarBackground”。
#define iOS10 ([[UIDevice currentDevice].systemVersion intValue]>=10?YES:NO)
NSArray *subviews=self.navigationController.navigationBar.subviews;
for (UIView *view in subviews) {
if (iOS10) {
//iOS10,改变了状态栏的类为_UIBarBackground
if ([view isKindOfClass:NSClassFromString(@"_UIBarBackground")]) {
view.hidden = YES;
}
}else{
//iOS9以及iOS9之前使用的是_UINavigationBarBackground
if ([view isKindOfClass:NSClassFromString(@"_UINavigationBarBackground")]) {
view.hidden = YES;
}
}
}
待续。。。