前言
Swift3即将发布release版本,WWDC2016上苹果也带来了介绍.点击这里看视频.本文主要是翻译和解释.另外原视频前面介绍了Swift是怎么开源的,最后谈到了如何提高效率.对于一般开发者并无大用,我这里也就不多说了.
API简化
许多API是从OBjective-C版本直接转成Swift版本,所以不够Swift化.苹果在Swift3中简化了大量API,使其语义更清晰,语法更简洁.举例如下:
// Swift 2
array.appendContentsOf([2,3,4])
array.insert(1, atIndex: 0)
// Swift 3
array.append(contentsOf: [2,3,4])
array.insert(1, at: 0)
// Swift 2
if url.fileURL {}
x = url.URLByAppendingPathComponent("file.txt")
// Swift 3
if url.isFileURL {}
x = url.URLByAppendingPathComponent("file.txt")
Objective-C API优化
1. Swift化
Objective-C中存在着大量的C式API,在Swift中显得格格不入.在Swift3中得以改进.如:
// Swift 2
func CGContextFillPath(_: CGContext)
// Swift 3
void CGContextFillPath(CGContextRef) NS_SWIFT_NAME(CGContext.fillPath(self:));
extension CGContext {
func fillPath()
}
2. Objective-C泛型支持
Objective-C本身是不支持泛型的,当我们使用某些通用的API是就相当痛苦.比如使用Core Data查询得到的结果,明明可以指定类型.在Swift3中是这样改进的:
// Swift 2
func findAnimals() {
let request = NSFetchRequest(entityName:”Animal")
guard let searchResults =
try? context.executeFetchRequest(request) as! [Animal] {
return
}
...
use(searchResults)
}
// Swift 3
func findAnimals() {
let request : NSFetchRequest<Animal> = Animal.fetchRequest
guard let searchResults = try? context.fetch(request) {
return
}
...
use(searchResults)
}
这里的guard语句的else漏掉了,我怀疑是演讲稿有问题,并不是修改了
3. String型的Enum改进
在Objective-C中String型的Enum到处可见(与C语言相关).而String的不安全性很大.使用者可以随意传入String从而导致Bug.在Swift3中对此也进行了优化.
// Swift 2
typedef NSString *NSNotificationName;
const NSNotificationName NSUserDefaultsDidChangeNotification;
let NSUserDefaultsDidChangeNotification: String // Imported definition
center.addObserver(forName: NSUserDefaultsDidChangeNotification, ...) // Use
// Swift 3
typedef NSString *NSNotificationName;NS_EXTENSIBLE_STRING_ENUM;
const NSNotificationName NSUserDefaultsDidChangeNotification;
extension UserDefaults {
class let didChangeNotification: NSNotification.Name
} // Imported definition
center.addObserver(forName: UserDefaults.didChangeNotification, ...) // Use
Core Language(语言特性)
1. 参数标签
首先就是方法的首个参数名称不再默认略去(这是Objective-C的命名特点).如:
func myFunction(a: Int, b: Int, c: Int) { }
// Swift 2
myFunction(42, b: 57, c: 99)
// Swift 3
myFunction(a: 42, b: 57, c: 99)
2. 泛型约束
泛型的约束条件过长引起阅读困难,将where部分挪至函数尾部.如:
// Swift 2
func anyCommon<T: Sequence, U: Sequence where T.Element: Equatable, T.Element == U.Element>(lhs: T, rhs: U) -> Bool {
// Swift 3
func anyCommon<T: Sequence, U: Sequence>(lhs: T, rhs: U) -> Bool where T.Element: Equatable, T.Element == U.Element {
3. 未使用返回值警告
现在允许将函数标记为@discardableResult用于不使用返回值且不警告.
@discardableResult
func plusOne(_ a: Int) -> Int {
print(a) // side effect!
return a+1
}
plusOne(4) // no warning
类型系统
1. UnsafeMutablePointer
在Swift2中可以将nil直接赋给UnsafeMutablePointer,苹果原本就是把UnsafeMutablePointer对待成不安全的指针.但是Swift3中苹果不愿再将其特殊化, UnsafeMutablePointer将与其他类型一样有可选型.
// Swift 3
let ptr : UnsafeMutablePointer<Int> = nil
let ptr : UnsafeMutablePointer<Int>? = nil
2. 隐式可选型
隐式可选型为用!
修饰的类型,它可以为nil,而且可以传给要求非nil的参数.不过当访问此值时会强制解包,如果为nil则会引起崩溃.Swift3中针对非可选型与隐式可选型相加得到的结果类型进行了改变.
func f(value : Int!) {
let x = value + 1 // x: Int - force unwrapped
let y = value // Swift2中 y: Int!, Swift3中 y: Int?
}
标准库
1. Collection的新Index
Swift对于Index的处理一直让人感觉捉襟见肘,Swift3中对于语法进行了改进.具体如下:
// Swift 2
i = collection.startIndex
next = i.successor()
// Swift 3
i = collection.startIndex
next = collection.index(after: i)
其他的改进还有:
- 半开区间和区间并入Range型
- 0...UInt8.max现可以正确生效
- 性能提升
2. 浮点数和数值
浮点数包含Float,Float80,Double和CGFloat.我想很多人应该疲于浮点型间的类型转换以及运算.在Swift3中pi值可以在任何浮点型中get到.而且浮点型间的运算无需再频繁转换.代码如下:
let v = 2 * Float.pi // 轻松get pi值
return x * CGFloat.pi / 180 // Float间运算无需转换
附录
关于新版本的改动还有非常多,有一些是一笔带过的,还有更多是没有提到的.在这里我以附录的形式呈现给大家,也方便以后补充.
- 柯里化函数声明被删除
- 函数参数声明不可使用var修饰(Closure一样)
- ++和--运算符被删除
- C式循环被删除 for (i=0;i<10;i++)...
- 移除了隐式元组
- 新增fileprivate访问级别
- case关键字可与多变量绑定
- 泛型支持别名(Type Aliases)