随着iOS10发布的临近,你们的App都须要适配iOS10,下面是我总结的一些关于iOS10适配方面的问题,若是有错误,欢迎指出.web
1.系统判断方法失效:
在你的项目中,当须要判断系统版本的话,不要使用下面的方法:算法
#define isiOS10 ([[[[UIDevice currentDevice] systemVersion] substringToIndex:1] intValue]>=10)
它会永远返回
NO
,substringToIndex:1
在iOS 10 会被检测成 iOS 1了,
应该使用下面的这些方法:
Objective-C 中这样写:api#define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame) #define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending) #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) #define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending) #define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
或者使用:数组
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}
有时候会缺乏一些常量,
NSFoundationVersionNumber
是在NSObjCRuntime.h
中定义的,做为Xcode7.3.1的一部分,咱们设定常熟范围从iPhone OS 2到#define NSFoundationVersionNumber_iOS_8_4 1144.17
,在iOS 10(Xcode 8)中,苹果补充了缺乏的数字,设置有将来的版本.ruby#define NSFoundationVersionNumber_iOS_9_0 1240.1 #define NSFoundationVersionNumber_iOS_9_1 1241.14 #define NSFoundationVersionNumber_iOS_9_2 1242.12 #define NSFoundationVersionNumber_iOS_9_3 1242.12 #define NSFoundationVersionNumber_iOS_9_4 1280.25 #define NSFoundationVersionNumber_iOS_9_x_Max 1299
Swift中这样写:网络
if NSProcessInfo().isOperatingSystemAtLeastVersion(NSOperatingSystemVersion(majorVersion: 10, minorVersion: 0, patchVersion: 0)) { // 代码块 }
或者使用app
if #available(iOS 10.0, *) { // 代码块 } else { // 代码块 }
你的项目中访问了隐私数据,好比:相机,相册,联系人等,在Xcode8中打开编译的话,通通会crash,控制台会输出下面这样的日志:框架
这是由于iOS对用户的安全和隐私的加强,在申请不少私有权限的时候都须要添加描述,可是,在使用Xcode 8以前的Xcode仍是使用系统的权限通知框.
要想解决这个问题,只须要在info.plist
添加NSContactsUsageDescription
的key, value本身随意填写就能够,这里列举出对应的key(Source Code模式下):dom
<!-- 相册 --> <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>
若是不起做用,能够请求后台权限,相似于这样:
<key>UIBackgroundModes</key> <array> <!-- 在这里写上你在后台模式下要使用权限对应的key --> <string>location</string> ... </array>
或者在Xcode里选中当前的target
,选择Capabilities
,找到Background Modes
,打开它,在里面选择对应权限
官方文档中说:大多数
core
开头的图形框架和AVFoundation
都提升了对扩展像素和宽色域色彩空间的支持.经过图形堆栈扩展这种方式比以往支持广色域的显示设备更加容易。如今对UIKit扩展能够在sRGB的色彩空间下工做,性能更好,也能够在更普遍的色域来搭配sRGB颜色.若是你的项目中是经过低级别的api本身实现图形处理的,建议使用sRGB,也就是说在项目中使用了RGB转化颜色的建议转换为使用sRGB,在UIColor
类中新增了两个api:- (UIColor *)initWithDisplayP3Red:(CGFloat)displayP3Red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha NS_AVAILABLE_IOS(10_0); + (UIColor *)colorWithDisplayP3Red:(CGFloat)displayP3Red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha NS_AVAILABLE_IOS(10_0);
4.真彩色的显示
真彩色的显示会根据光感应器来自动的调节达到特定环境下显示与性能的平衡效果,若是须要这个功能的话,能够在
info.plist
里配置(在Source Code模式下):<key>UIWhitePointAdaptivityStyle</key>
它有五种取值,分别是:
<string>UIWhitePointAdaptivityStyleStandard</string> // 标准模式 <string>UIWhitePointAdaptivityStyleReading</string> // 阅读模式 <string>UIWhitePointAdaptivityStylePhoto</string> // 图片模式 <string>UIWhitePointAdaptivityStyleVideo</string> // 视频模式 <string>UIWhitePointAdaptivityStyleStandard</string> // 游戏模式
也就是说若是你的项目是阅读类的,就选择
UIWhitePointAdaptivityStyleReading
这个模式,五种模式的显示效果是从上往下递减,也就是说若是你的项目是图片处理类的,你选择的是阅读模式,给选择太好的效果会影响性能.5.ATS的问题
1.在iOS 9的时候,默认非HTTS的网络是被禁止的,咱们能够在
info.plist
文件中添加NSAppTransportSecurity
字典,将NSAllowsArbitraryLoads
设置为YES
来禁用ATS;
2.从2017年1月1日起,,全部新提交的 app 默认不容许使用NSAllowsArbitraryLoads
来绕过ATS的限制,默认状况下你的 app 能够访问加密足够强的(TLS V1.2以上)HTTPS内容;
3.能够选择使用NSExceptionDomains
设置白名单的方式对特定的域名开放HTTP内容来经过审核,好比说你的应用集成了第三方的登陆分享SDK,能够经过这种方式来作,下面以新浪SDK做为示范(Source Code 模式下):<key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>sina.cn</key> <dict> <key>NSThirdPartyExceptionMinimumTLSVersion</key> <string>TLSv1.0</string> <key>NSThirdPartyExceptionRequiresForwardSecrecy</key> <false/> <key>NSIncludesSubdomains</key> <true/> </dict> <key>weibo.cn</key> <dict> <key>NSThirdPartyExceptionMinimumTLSVersion</key> <string>TLSv1.0</string> <key>NSThirdPartyExceptionRequiresForwardSecrecy</key> <false/> <key>NSIncludesSubdomains</key> <true/> </dict> <key>weibo. com</key> <dict> <key>NSThirdPartyExceptionMinimumTLSVersion</key> <string>TLSv1.0</string> <key>NSThirdPartyExceptionRequiresForwardSecrecy</key> <false/> <key>NSIncludesSubdomains</key> <true/> </dict> <key>sinaimg.cn</key> <dict> <key>NSThirdPartyExceptionMinimumTLSVersion</key> <string>TLSv1.0</string> <key>NSThirdPartyExceptionRequiresForwardSecrecy</key> <false/> <key>NSIncludesSubdomains</key> <true/> </dict> <key>sinajs.cn</key> <dict> <key>NSThirdPartyExceptionMinimumTLSVersion</key> <string>TLSv1.0</string> <key>NSThirdPartyExceptionRequiresForwardSecrecy</key> <false/> <key>NSIncludesSubdomains</key> <true/> </dict> <key>sina.com.cn</key> <dict> <key>NSThirdPartyExceptionMinimumTLSVersion</key> <string>TLSv1.0</string> <key>NSThirdPartyExceptionRequiresForwardSecrecy</key> <false/> <key>NSIncludesSubdomains</key> <true/> </dict> </dict> </dict>
4.在iOS 10 中
info.plist
文件新加入了NSAllowsArbitraryLoadsInWebContent
键,容许任意web页面加载,同时苹果会用 ATS 来保护你的app;
5.安全传输再也不支持SSLv3
, 建议尽快停用SHA1
和3DES
算法;6.UIStatusBar的问题:
在iOS10中,若是还使用之前设置UIStatusBar类型或者控制隐藏仍是显示的方法,会报警告,方法过时,以下图:
![]()
UIStatusBar的警告.png
上面方法到 iOS 10 不能使用了,要想修改UIStatusBar的样式或者状态使用下图中所示的属性或方法:@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
7.UITextField
在iOS 10 中,
UITextField
新增了textContentType
字段,是UITextContentType
类型,它是一个枚举,做用是能够指定输入框的类型,以便系统能够分析出用户的语义.是电话类型就建议一些电话,是地址类型就建议一些地址.能够在#import <UIKit/UITextInputTraits.h>
文件中,查看textContentType
字段,有如下能够选择的类型:UIKIT_EXTERN UITextContentType const UITextContentTypeName NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypeNamePrefix NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypeGivenName NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypeMiddleName NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypeFamilyName NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypeNameSuffix NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypeNickname NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypeJobTitle NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypeOrganizationName NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypeLocation NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypeFullStreetAddress NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypeStreetAddressLine1 NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypeStreetAddressLine2 NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypeAddressCity NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypeAddressState NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypeAddressCityAndState NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypeSublocality NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypeCountryName NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypePostalCode NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypeTelephoneNumber NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypeEmailAddress NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypeURL NS_AVAILABLE_IOS(10_0); UIKIT_EXTERN UITextContentType const UITextContentTypeCreditCardNumber NS_AVAILABLE_IOS(10_0);
8.UserNotifications(用户通知)
iOS 10 中将通知相关的 API 都统一了,在此基础上不少用户定义的通知,而且能够捕捉到各个通知状态的回调.之前通知的概念是:你们想接受的提早作好准备,而后一下全两分发,没收到也无论了,也不关心发送者,如今的用户通知作成了相似于网络请求,先发一个
request
获得response
的流程,还封装了error
,能够在各个状态的方法中作一些额外的操做,而且能得到一些字段,好比发送者之类的.这个功能的头文件是:#import <UserNotifications/UserNotifications.h>
主要有如下文件:
#import <UserNotifications/NSString+UserNotifications.h> #import <UserNotifications/UNError.h> #import <UserNotifications/UNNotification.h> #import <UserNotifications/UNNotificationAction.h> #import <UserNotifications/UNNotificationAttachment.h> #import <UserNotifications/UNNotificationCategory.h> #import <UserNotifications/UNNotificationContent.h> #import <UserNotifications/UNNotificationRequest.h> #import <UserNotifications/UNNotificationResponse.h> #import <UserNotifications/UNNotificationSettings.h> #import <UserNotifications/UNNotificationSound.h> #import <UserNotifications/UNNotificationTrigger.h> #import <UserNotifications/UNUserNotificationCenter.h> #import <UserNotifications/UNNotificationServiceExtension.h>
在iOS 10 以前,UICollectionView上面若是有大量cell,当用户活动很快的时候,整个UICollectionView的卡顿会很明显,为何会形成这样的问题,这里涉及到了iOS 系统的重用机制,当cell准备加载进屏幕的时候,整个cell都已经加载完成,等待在屏幕外面了,也就是整整一行cell都已经加载完毕,这就是形成卡顿的主要缘由,专业术语叫作:掉帧.
要想让用户感受不到卡顿,咱们的app必须帧率达到60帧/秒,也就是说每帧16毫秒要刷新一次.
prepareForReuse
方法,在这个方法里面,能够重置cell的状态,加载新的数据;cellForItemAtIndexPath
方法,在这个方法里面给cell赋值模型,而后返回给系统;willDisplayCell
方法,在这个方法里面咱们还能够修改cell,为进入屏幕作最后的准备工做;willDisplayCell
方法后,cell就进去屏幕了.当cell彻底离开屏幕之后,会调用didEndDisplayingCell
方法.prepareForReuse
方法,在这里当cell尚未进去屏幕的时候,就已经提早调用这个方法了,对比以前的区别是以前是cell的上边缘立刻进去屏幕的时候就会调用该方法,而iOS 10 提早到cell还在屏幕外面的时候就调用;cellForItemAtIndexPath
中建立cell,填充数据,刷新状态等操做,相比于以前也提早了;willDisplayCell
方法,原则就是:什么时候须要显示,什么时候再去调用willDisplayCell
方法;didEndDisplayingCell
方法,跟以前同样,cell会进入重用队列.cellForItemAtIndexPath
建立或者生成一个cell.willDisplayCell
方法就能够从新出如今屏幕中了.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一样适用.
在iOS 10 中, UIRefreshControl能够直接在UICollectionView和UITableView中使用,而且脱离了UITableViewController.如今RefreshControl是UIScrollView的一个属性.
使用方法:
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init]; [refreshControl addTarget:self action:@selector(loadData) forControlEvents:UIControlEventValueChanged]; collectionView.refreshControl = refreshControl;
你们遇到问题欢迎向我提出,我会不断完善这个项目.