适配 iOS 10 时遇到的一些坑
关于 Xcode 8 和 iOS 10 的文章其实已经有很多了,完全可以解决适配过程中遇到的大部分问题。我参照的是 iOS 10 的适配问题 这篇文章,除了没有提到关于 Automatically manage signing 的问题,其他问题大致都涉及到了。而且那个自己也很好解决,勾选然后选择正确的 Team 就好了。就算包含了推送等功能,只要之前设置没问题,Xcode 8 也是可以自动识别配置成功的。所以我这里讨论的只是我在适配过程中遇到的几个坑。
关于推送
代码上改变最大的就是关于推送的了,具体的改变可以看 活久见的重构 - iOS 10 UserNotifications 框架解析的具体分析。
而像我这样直接用极光推送 API 实现的就简单多了,可以下载官方 mode 参考。
首先要导入 #import <UserNotifications/UserNotifications.h>
,然后需要遵守 JPUSHRegisterDelegate
。官方的是 UNUserNotificationCenterDelegate
,在这里极光进行了封装。
然后注册通知的代码变成了这样:
1
2
3JPUSHRegisterEntity * entity = [[JPUSHRegisterEntity alloc] init];
entity.types = UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound;
[JPUSHService registerForRemoteNotificationConfig:entity delegate:self];
当然,为了兼容低版本最好加上以下代码:
1
2#ifdef NSFoundationVersionNumber_iOS_9_x_Max
#endif
获得 Device Token 的方法并没有改变,但是接收通知的代码变成了之前注册的 JPUSHRegisterDelegate 的两个方法。其中接收通知的代码是 - (void)jpushNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger options))completionHandler;
,我在这个方法里处理应用处于前台时的情况。通知的点击事件是 - (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler;
,我在这里处理应用处于后台时的情况。
最后,最最重要的是一定一定一定要记得打开 Push Notifications 的开关!!!这个在之前是不作要求的,但 iOS 10 必须。
关于 Swift 3
打开项目满眼的警告其实是早已预料到的,具体可以看 Swift 3 新特性一览。还好 Xcode 的转换器虽然说有点坑(不要像我一样傻得按它的提示一个一个加 as AnyObjct?
,只要把前面的 [String:AnyObject]
改为 [String:Any]
就可以了),但也可以帮我们解决其中的大半部分。剩下的就是改变非常大需要我们自己手动的了。
第三方框架
第三方框架对 Swift 3 的支持是不一样的。
像 Alamofire 这种支持的直接 pod 'Alamofire', '~> 4.0'
升级最新版本就好了。当然在这之前需要先升级 CocoaPods。
而 SRKControls 这种 master 不支持,但是在其他的 branch 里,或者有热心网友的。pod 'SKPhotoBrowser', :git => 'https://github.com/suzuki-0000/SKPhotoBrowser.git', :branch => 'swift3'
或者 pod 'SRKControls', :git => 'https://github.com/sag333ar/SRKControls.git', :branch => 'master'
就好了。这需要你在 Issues 或者 branches 里找一找。
最后就是 KGFloatingDrawer 这种小众的,作者也没有修改的迹象。那就自己动手好了┐(´ー`)┌ 自己做这个热心网友~当然,如果自己懒得改那就去重找一个支持 Swift 3 的相似框架。但实在不好说哪个更省事一些。
更优雅的 Swift 框架
为了适应 Swift 3 的代码风格,RxSwift 的 rx_
前缀变成了 rx.
,SnapKit 的 snp_
前缀变成了 snp.
,Kingfisher 的 kf_
前缀变成了 kf.
。全局替换下就好了。
GCD
Swift 3 对 GCD 的改变是我期待已久的事情,原来的风格真的和其它的代码很不搭~
说明 | Old | Swift 3 |
---|---|---|
主队列 | dispatch_get_main_queue() | DispatchQueue.main |
全局并行队列 | dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) | DispatchQueue.global() |
串行队列 | dispatch_queue_create("queue0", DISPATCH_QUEUE_SERIAL) | DispatchQueue(label: "queue0") |
并行队列 | dispatch_queue_create("queue1", DISPATCH_QUEUE_CONCURRENT) | DispatchQueue(label: "queue1", attributes: .concurrent) |
异步任务 | dispatch_async | .async |
同步任务 | dispatch_sync | .sync |
只执行一次 | dispatch_once | 没了 |
组 | dispatch_group_create() | DispatchGroup() |
操作执行完了再继续 | dispatch_group_wait | group.wait() |
操作都完成后执行 | dispatch_group_notify | group.notify(queue: DispatchQueue.main) |
其中 dispatch_once
直接被删除了,要用单例只有懒加载了。
1
2static let shareEventListViewModel = CAEventListViewModel()
fileprivate override init() { }
当然其它 C 风格的代码也改了,比如 NSStringEncodingUTF8
现在需要写成 String.Encoding.utf8
。这里就不多赘述了。