首页 » Swift » Swift3.2 到Swift4 的升级工作

Swift3.2 到Swift4 的升级工作

原文 http://blog.csdn.net/dangyalingengjia/article/details/79072591

2018-01-18 02:01:27阅读(255)

最近完成了公司项目由Swift3.2 -> Swift4的升级工作,记录一下。
这里将Swift4较Swift3.2的新特性以及必要的处理列出来:

1,private关键字作用域扩大到整个文件。
说明:可以用private替代fileprivate了
处理建议:考虑到private没有向后兼容性(在swift3.2及之前版本无法在extension中使用),所以建议保留原来的fileprivate关键字。

2,扩展Key Path的写法
说明:
Swift 3.2中Key Path写法:

class Kid: NSObject {
     var nickname: String = ""
     var age: Double = 0.0
     var friends: [Kid] = []
    init(nickname: String, age: Double) {
        self.nickname = nickname
        self.age = age
    }
}
class ViewController {
    func testKeyPath() {
        var ben = Kid(nickname: "Benji", age: 5.5)
        let kidsNameKeyPath = #keyPath(Kid.nickname)
        ben.setValue("Ben", forKeyPath: kidsNameKeyPath)
    }
}

Swift4中增加的写法:

func testKeyPath() {
    let ben = Kid(nickname: "Benji", age: 5.5)
    let kidsNameKeyPath = \Kid.nickname
    ben[keyPath: \Kid.nickname] = "Ben"
}

处理建议:代码可以不用改,见了\的用法认识就可以。

3,关于@objc的使用
说明:
Swift编译器会推断需要暴露给OC的函数(所有继承于NSObject的类的函数),并为其增加@objc关键字修饰。这样做的问题有:
(1)增大二进制文件大小。
(2)程序员不知道编译器何时会推断为需要增加@objc

用Swift4编译代码时,在check dependencies这一步,提示:

The use of Swift 3 @objc inference in Swift 4 mode is deprecated. Please address deprecated @objc inference warnings, test your code with “Use of deprecated Swift 3 @objc inference” logging enabled, and then disable inference by changing the “Swift 3 @objc Inference” build setting to “Default” for the “XXX” target.

按照提示将xxx target - build setting- Swift 3 @objc Inference 由On改为Default之后,#selector的函数以及dynamic变量如果没有用@objc修饰的话,会报错:
Argument of ‘#selector’ refers to instance method ‘xxx()’ that is not exposed to Objective-C
给#selector中的函数和dynamic变量前面加上@objc就可以了。
处理建议:必须按照说明中的方法修改,否则编译报错。

4,结构体UILayoutPriority中的运算符重载被删除
说明:
setContentCompressionResistancePriority(_:for:)等方法的参数类型是结构体UILayoutPriority。
Swift3.2写法:

self.detail1Label.setContentCompressionResistancePriority(UILayoutPriorityDefaultLow-10, for: UILayoutConstraintAxis.horizontal)
self.detail2Label.setContentHuggingPriority(UILayoutPriorityRequired, for: UILayoutConstraintAxis.horizontal)

Swift4写法:

self.detail1Label.setContentCompressionResistancePriority(UILayoutPriority(rawValue: UILayoutPriority.RawValue(Int(UILayoutPriority.defaultLow.rawValue)-10)), for: UILayoutConstraintAxis.horizontal)
self.detail2Label.setContentHuggingPriority(UILayoutPriority.required, for: UILayoutConstraintAxis.horizontal)

处理建议:必须按照说明中的方法修改,否则编译报错。

5,NSAttributedString相关OC的全局变量无法在Swift4中继续使用
说明:
看下这段代码:

let textMATString = NSMutableAttributedString(string: "abcd")
let titleOptions: [String : Any] = [NSFontAttributeName : UIFont.systemFont(ofSize: 12)]
textMATString.addAttributes(titleOptions, range: NSMakeRange(0, 4))

这段代码在Swift3.2上编译无问题,但是在Swift4上报错:
Cannot convert value of type ‘NSAttributedStringKey’ to expected dictionary key type ‘String’
查了SDK,NSFontAttributeName是OC中的全局变量名,在Swift中相应的是NSAttributedStringKey.font。看来Swift4中严格限制了OC中的全局变量在Swif4中的使用。

以下是Swift4中的写法:

let titleOptions: [NSAttributedStringKey : Any] = [NSAttributedStringKey(rawValue: NSAttributedStringKey.font.rawValue) : UIFont.systemFont(ofSize: 12)]

处理建议:必须按照说明中的方法修改,否则编译报错。

6,更严格的Block参数检查
说明:
Swift4中对Block中参数的个数进行了严格的检查,即使是用_表示的未使用参数,个数也要严格对应才能编译通过。
例如,Kingfisher中的Block定义

DownloadProgressBlock = ((_ receivedSize: Int64, _ totalSize: Int64) -> ())

使用方式:

KingfisherManager.shared.retrieveImage(with: url, options: options, progressBlock: {_ in}, completionHandler: { [weak self] (image, error, cacheType, url) in

上面的代码Swift3.2中编译正常,Swift4中报错:
Cannot convert value of type ‘(_) -> ()’ to expected argument type ‘DownloadProgressBlock?’ (aka ‘Optional<(Int64, Int64) -> ()>’)
修正方式:

KingfisherManager.shared.retrieveImage(with: url, options: options, progressBlock: {_, _ in}, completionHandler: { [weak self] (image, error, cacheType, url) in
or
KingfisherManager.shared.retrieveImage(with: url, options: options, progressBlock: nil, completionHandler: { [weak self] (image, error, cacheType, url) in

处理建议:使用时需要符合block中参数的个数

7,AVCaptureDevice、AVCaptureSession、AVMediaType等类中的全局变量无法在Swift4中继续使用
说明:
会有编译error。
处理建议:
按照提示修改即可。

在参考文档中讲解的下面的功能点经证实在Swift3.2就已经有了,并不是Swif4新增加的功能:
1,有些教程中说“类型和协议的组合类型”是Swift4中新增加的特性,这是错误的,在Swift3.2就已经有个这个特性,在代码中指定类型为(类型 & 协议)是不会报错的。
2,用”“”控制字符串可以实现多行字符串字面量。
3,对于字典集合的顺序初始化,过滤等内容。

参考:
1,最全的 Swift 4 新特性解析 https://www.jianshu.com/p/c4f5db08bcab
2,What’s New in Swift 4? https://www.raywenderlich.com/163857/whats-new-swift-4

最新发布

CentOS专题

关于本站

5ibc.net旗下博客站精品博文小部分原创、大部分从互联网收集整理。尊重作者版权、传播精品博文,让更多编程爱好者知晓!

小提示

按 Ctrl+D 键,
把本文加入收藏夹