项目迁移至swift2.3并适配iOS10

因为项目里用到的有些第三方库还没有兼容swift3,所以只有先迁移到swift2.3,过程记录如下:

  1. 先执行pod outdated,看下有哪些三方库版本较低需要升级,需要升级的库去其github主页上看下是否已经支持swift2.3了,支持的话那就指定swift2.3对应的版本号;若只支持swift3的,那还是指定原来较老的版本号。

  2. Podfile添加如下代码:

    1
    post_install do |installer|
       installer.pods_project.build_configurations.each do |config|
            config.build_settings['SWIFT_VERSION'] = '2.3'
            config.build_settings['PROVISIONING_PROFILE_SPECIFIER'] = '团队ID/'
            config.build_settings['ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES'] = 'NO'
        end
    end
  3. 接着执行pod update后,我在这里遇到一个错误:The 'Pods-xxx' target has frameworks with conflicting names: UMMobClick。解决方案:先把友盟库注释掉,重新执行pod update,这下没问题了;我又尝试重新添加友盟库再update,之前的错误竟没了,靠。

  4. Xcode8打开项目,弹窗要求convert,这里选择Convert to Swift2.3,新的弹窗要求勾选需要转换的代码库,保持默认勾选即可。接下来静待converting。

  5. convert完了后运行项目,冒出一些语法错误,看来没有彻底convert。不过相比于swift3的大量语法改变,swift2.3需要改的并不多,根据错误提示一一解决。

  6. 重新运行项目,又有个错误:Module file was created by an older version of the compiler; rebuild 'RealmSwift' and try again。我在作迁移时,Realm官网还仍然是老的1.0.2版本(现在已经发布了1.1.0版本包括swift2.3和swift3的framework),于是只有自己git clone https://github.com/realm/realm-cocoa.git,然后执行:REALM_SWIFT_VERSION=2.3 sh build.sh ios-swift,最后报错:xcodebuild: error: Unable to find a destination matching the provided destination specifier: { name:iPhone 6 }。解决方案:修改build.sh的132行为destination="iPhone 7",再重新执行上面的编译脚本,成功编译得到Realm.framework和RealmSwift.framework,替换项目里老的framework。

  7. 再次运行项目,Build Success,不过还没完。


适配iOS10

  1. Info.plist添加:NSPhotoLibraryUsageDescriptionNSCameraUsageDescription,其他权限参看http://www.jianshu.com/p/f8151d556930

  2. 推送通知:

  • 项目设置的Capabilities里开启Push Notifications,会自动生成xxx.entitlements文件,记得提交审核打包时把development改为production
  • AppIcon添加Icon-20的2x,3x图标
  • 我们用的是百度推送,也已经有了新版,更新至1.4.7
  • AppDelegate的didFinishLaunchingWithOptions函数添加:
1
if #available(iOS 10.0, *) {
	UNUserNotificationCenter.currentNotificationCenter().delegate = PushNotificationService.instance
}
  • 注册推送:
1
func registerNotification() {
    if #available(iOS 10.0, *) {
        UNUserNotificationCenter.currentNotificationCenter()
            .requestAuthorizationWithOptions([.Alert, .Badge, .Sound]) { granted, error in
                if granted {
                    UIApplication.sharedApplication().registerForRemoteNotifications()
                } else if let err = error {
                    log.error("registerForRemoteNotifications err=\(err)")
                }
        }
    } else {
        let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound],
                                                  categories: nil)
        UIApplication.sharedApplication().registerUserNotificationSettings(settings)
    }
}
  • 实现UNUserNotificationCenterDelegate代理函数
1
@available(iOS 10.0, *)
extension PushNotificationService: UNUserNotificationCenterDelegate {

    //点击推送通知都会调用该函数
    func userNotificationCenter(center: UNUserNotificationCenter, didReceiveNotificationResponse response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void) {
        handleNotification(response.notification.request.content.userInfo,
                           applicationState: UIApplication.sharedApplication().applicationState)
        completionHandler()
    }
}
  1. 字体变宽导致文字显示不全,我们项目里有这种情况的是因为设置了label的宽度约束。除了删除宽度约束再修改其他约束条件来使UI与以前一样外,另外更简便的方法是可以设置UILabel的minimumScaleFactor,IB里同样可以设置,保持0.5就好

  2. 我们项目里有把UITableViewCell和UITableViewHeaderFooterView用在除TableView的其他地方。之前代码设置高度约束是作用于cell上,在iOS10设备上运行会出现约束冲突,显示也有问题。把高度约束作用于cell.contentView上就OK了,代码如下(autolayout三方库用的是EasyPeasy,个人认为代码书写上比snapkit要简洁些):

1
if #available(iOS 10.0, *) {
    cell.contentView <- Height(110)
} else {
    cell <- Height(110)
}

2个项目利用中秋假期的两天完成迁移和代码适配,问题解决,总的来说比想象中容易些。迁移至swift3有困难的朋友,不妨先迁到swift2.3,至少可以让项目能在Xcode8上跑起来。

参考网址:
http://swift.gg/2016/09/02/xcode7-xcode8/
http://stackoverflow.com/questions/38888454/how-to-build-realm-using-swift-2-3
https://onevcat.com/2016/08/notification/
http://www.jianshu.com/p/f8151d556930
http://www.jianshu.com/p/9756992a35ca