Swift 2.3-> 3.0

主宰稳场 提交于 2019-12-03 10:21:08

是否从Swift2.3升级到3.0呢?

如果你有一个意义非常重大的Swift编码库(就像我们在VTS中做的一样),那么别犹豫了,赶快更新吧。另外为了项目的需要,Xcode的更新,跟随苹果的步伐,最新的技术,还是麻溜的跟上把。

但是如果你的Swift代码不是非常的繁重,那么你就直接忽略2.3吧。

下面有一些事情需要记住:

1.依赖库非常重要,确保你的依赖库支持2.3还是3.0-大多数的lib/framework是两者都支持的(Alamofire,Charts).然而升级到3.0是你的唯一途径。新的发展将会在Swift3.0展开。所有的swift2.3版本的相关依赖库将会被冻结,也就是不在更新。

2.Xcode8.x 将会移除对Swift2.3的支持。Swift2.3注定是大型工程的一个过渡品。所以我们需要努力的升级到swift3.0

3.如果你有一个私有的CocoaPods用于分享代码在多个工程中,那么你不得不马上更新。

当然你可以只更新到2.3,但是你只能推迟,因为在发布Xcode9之前你必须移植到Swift3。

 

将问题从Swift2.2迁移到2.3

这个迁移可能将Range<T>到CountableRange<T>.但是CountableRange<T>只存在于Swift3

迁移者将会添加评论 /* 迁移者 修复:使用变量类型为: DispatchSpecificKey*/去使用dispatch_queue_set_specific() 这是唯一未来相关在Swift3迁移中。

 

将问题从Swift2.x迁移到3.0

Swift3.0是一个打破一切的版本。swift3意味着打破一切并且移除了所有不利于一个语言长期发展的不利因素。这当然也意味着很多的东西被改变了。你也需要去改变这些使你的工程更加兼容。

 

Swift 2.3

Swift2.3是一个非常小的更新。具体多么小呢?实际上,这里仅仅只有一个改变。OC代码在编译时为空的检查在苹果的SDK中被更新。

// Swift 2.2
  let image = CIImage(MTLTexture: texture, options: options)
  let extent = image.extent // can crash
   
  // Swift 3.0
  let image = CIImage(MTLTexture: texture, options: options)!
  // or
  if let image = CIImage(MTLTexture: texture, options: options) {
 
  }

其他的变化包括一些小的重命名和一些可选类型的初始化现在返回了他们应该返回的类型而不再是可选类型。这些应用就想从bundle初始化nib一样。

 

Swift3.0

重大的更改(你必须需要注意)

私有的定义已经被更改了,下面来介绍一下fileprivate

以前格式化的私有现在在Swift3.0中变成了fileprivate。一个fileprivate可以使用在一个Extension中

但是一个私有private的变量不可以使用在一个Extension的类中

学习更多的关于这个变化,请点击这里

public的定义也被改变了。下面来介绍一下open的定义

目前,声明一个类或者属性public提供了两种实用性:

1.允许外部的modules使用class/member.

2.允许外部的modules继承class/member.

在swift3中,public就是外部可用的,但是不能继承。以前的功能被open给封装了。

学习更多的关于这个变化,请点击这里

 

动词和名词

以d结尾的函数现在返回这个对象的一个实例

// Before
  var myArray = [ 1 ,3, 2, 5, 4 ]
  myArray.sort() // returns a new sorted version of `myArray`
  myArray.sortInPlace() // sorts in place
   
  // After
  myArray.sort() // sorts in place
  myArray.sorted() // returns a new sorted version of `myArray`.

 

这个变化同样适用于reverse和reversed,enumerate和enumerated等等

 

OC的布尔类型现在全部使用前缀 is ,Foundation 类型不再使用NS前缀了(这将不会有冲突,例如NSString仍然有前缀,要不然这将会和String冲突)

 

Foundation类型现在可以使用Swift的let和var定义非常nice的展示出来

//before
  var myDate = Date()
  myDate.addTimeInterval(60) // OK
   
  //after
  let myOtherDate = Date()
 

myOtherDate.addTimeInterval(60) // Error, as expected

 

学习更多的关于这个变化,请点击这里

 

引入作为一个成员

现在的C函数将会被引入作为方法。导入者将会经常自动地推断这些map。那就意味着使用老的C的API感觉更自然了,更和谐在Swift。就拿point为例。CoreGraphics API。CoreGraphics已经不再更新了在这个版本中

  // Before
  let topLeft = bounds.origin
  let bottomRight = CGPoint(x: bounds.size.width, y: bounds.size.height)
  let path = CGPathCreateMutable()
  CGPathMoveToPoint(path, &transform, topLeft.x, topLeft.y)
  CGPathAddLineToPoint(path, &transform, CGRectGetMidX(bounds), bottomRight.y)
  CGPathAddLineToPoint(path, &transform, bottomRight.x, topLeft.y)
  CGPathAddLineToPoint(path, &transform, topLeft.x, topLeft.y)
  CGPathAddLineToPoint(path, &transform, topLeft.x, bottomRight.y)
  CGPathAddLineToPoint(path, &transform, bottomRight.x, bottomRight.y)
  CGPathAddLineToPoint(path, &transform, bottomRight.x, topLeft.y)
  CGContextAddPath(context, path)
   
  // After
  let topLeft = bounds.origin
  let bottomRight = CGPoint(x: bounds.size.width, y: bounds.size.height)
  let path = CGMutablePath()
  path.move(transform: &transform, x: topLeft.x, y: topLeft.y)
  path.addLine(transform: &transform, x: bounds.midX, y: bottomRight.y)
  path.addLine(transform: &transform, x: bottomRight.x, y: topLeft.y)
  path.addLine(transform: &transform, x: topLeft.x, y: topLeft.y)
  path.addLine(transform: &transform, x: topLeft.x, y: bottomRight.y)
  path.addLine(transform: &transform, x: bottomRight.x, y: bottomRight.y)
  path.addLine(transform: &transform, x: bottomRight.x, y: topLeft.y)
  context.addPath(path)

 

学习更多的关于这个变化,请点击这里

 

驼峰标示的改变

在枚举和属性中。首字母大写的驼峰标示已经被小写所代替

// Before let red = UIColor.redColor().CGColor

// After let red = UIColor.red.cgColor

 

(我最喜欢的改变)重构了条件条款

你将不能在guard,if,while里面使用where关键词了。但是你仍然可以将他应用在循环(for-in-where)

// Before
  if let x = x where z == 2 {
  // Do stuff
  }
   
  // After
  if let x = x, z == 2 {
  // Do stuff
  }

 

仍然还有一些改变在case的条款中

学习更多的关于这个变化,请点击这里

 

第一个参数标签的一致性

第一个参数的名字默认是必须的现在

func remix(aSong: Song) {
...  
}  
   
// Before  
let song = Song()  
remix(song)  
   
// After  
let song = Song()  
remix(aSong: song)  

 

学习更多的关于这个变化,请点击这里

 

(我最喜欢的改变)处理了隐式的打开可选类型

我认为如果你有一个分享的语言,那么在迁移的过程中这个改变是值得的。那么到底是什么呢?

OC类型以前只有隐式解包类型!的属性。但是现在有了包裹类型?这可以被用到任何地方除了这里:

let legacyType = SomeObjCObject()

let starsArray = legacyType.stars     // Array of [Star!] 

学习更多的关于这个变化,请点击这里

 

更好的翻译关于OC的API

命名更加的清晰明确了

let path = UIBezierPath()
let point = CGPoint(x: 2, y: 3)  
let string = NSString("Hello world!")  
// Before  
path.moveToPoint(point)  
string.characterAtIndex(3)  
// After  
path.move(to: point)  
string.character(at: 3)  

 

学习更多的关于这个变化,请点击这里

 

现代化的调度:dispatching

// Before
let queue = dispatch_queue_create("com.test.myqueue", nil)  
dispatch_async(queue) {  
print("Hello World")  
}  
// After  
let queue = DispatchQueue(label: "com.test.myqueue")  
queue.asynchronously {  
print("Hello World")  
}  

学习更多的关于这个变化,请点击这里

 

集合类型有了新的展现形式

以前,当你想要在集合类型中从一个index一到另外一个,你需要使用index的successor方法。但是现在你使用c.index(after:index)就可以让collection之间的移动成为现实。collection现在有了一个任何可比较类型的index

 

myIndex.successor() => myCollection.index(after: myIndex)
myIndex.predecessor() => myCollection.index(before: myIndex)  
myIndex.advance(by: …) => myCollection.index(myIndex, offsetBy: …)  

 

(下面的模块除非是自己手动创建Range对象,否则我认为没有多大作用)

一方面,Range已经被划分为很多的类型。Range, ClosedRange, CountableRange, and CountableClosedRange.ClosedRange现在包括ranges扩宽了最大值类型(0...Int8.max).Range和ClosedRange 已经不能迭代了。他们现在需要一个可比较的对象作为他们的结合(所以你可以创建Range<String>)

学习更多的关于这个变化,请点击这里

OC的id已经被导入作为Swift的Any 类型

引用苹果的话是:

Since ‘id’ now imports as ‘Any’ rather than ‘AnyObject’, you may see errors where you were previously performing dynamic lookup on ‘AnyObject’.

由于id类型被当做了Any类型而不是AnyObject,所以你可能会看到一些错误当你先前查找AnyObject的动态类型时候。

学习更多的关于这个变化,请点击这里

一些很小的改变(你也许都没有注意到)

可选的操作符比较已经被移除

现在nil类型时可以比较的。案例:[3,nil,1,2].sorted()  // return [nil,1,2,3]

现在你需要解包可选类型在你比较之前(如下):

 

// Before
let a: Int = 4  
let b: Int? = 5  
if a > b { ... }  
   
// After  
guard let b = b, a > b else { ... }  
// or  
if let b = b {  
if a > b { ... }  
}  
// or  
if let b = b, a > b { ...}  

这也许是一件好事,但是可能拆除你的单元测试

学习更多的关于这个变化,请点击这里

 

闭包的参数名字和标签

很多的闭包参数的名字已经被重命名或者已经作为了可选

例如:

// before
words.sort(isOrderedBefore: >)  
let sum = measurements.reduce(0, combine: +)  
   
// after  
words.sort(by: >)  
let sum = measurements.reduce(0, +)  

 

flattern 重命名为joined

学习更多的关于这个变化,请点击这里

处理UnsafePointer<T>

非对象的指针类型为空行使用可选类型表示

学习更多的关于这个变化,请点击这里

Rounding floating (四舍五入浮点值是一个值的责任,现在)

以前我们使用全局的C函数floor和ceil去四舍五入一个浮点值类型。这些函数仍然可以使用但是已经考虑呗废弃。

因此我们应该采用如下方式:

(4.4).rounded() // == 4.0
(4.5).rounded() // == 5.0  
(4.0).rounded(.up) // == 4.0  
(4.9).rounded(.down) // == 4.0  
(4.0).rounded(.down) // == 4.0  

 

这里还有另外的rounding的规则,如下:

  1. toNearestOrAwayFromZero
  2. toNearestOrEven
  3. towardZero
  4. awayFromZero

学习更多的关于这个变化,请点击这里

泛型类型的别名(Generic type aliases)

学习更多的关于这个变化,请点击这里

操作符的声明有了语法的改变

// Before
infix operator <> { precedence 100 associativity left }  
   
// After  
precedencegroup ComparisonPrecedence {  
associativity: left  
higherThan: LogicalConjunctionPrecedence  
}  
infix operator <> : ComparisonPrecedence  

 

学习更多的关于这个变化,请点击这里

OC的常量现在有了Swift类型

我们不再使用名字字符串作为OC的内在操作符

// Before
// HealthKit has the following strings:  
HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyMassIndex;  
HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyFatPercentage;  
HK_EXTERN NSString * const HKQuantityTypeIdentifierHeight;  
HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyMass;  
HK_EXTERN NSString * const HKQuantityTypeIdentifierLeanBodyMass;  
// They were previously imported as swift Strings  
   
// After  
// Instead of importing this as a string, Swift will import this like so:  
enum HKQuantityTypeIdentifier : String {  
case BodyMassIndex  
case BodyFatPercentage  
case Height  
case BodyMass  
case LeanBodyMass  
}  

 

学习更多的关于这个变化,请点击这里

这些东西可能太小你根本没有注意到

NSError 已经提供了桥梁

// Before

catch let error as AVError where error == .diskFull {

 

 

 
// AVError is an enum, so one only gets the equivalent of the code.  
// There is no way to access the localized description (for example) or  
// any other information typically stored in the ``userInfo`` dictionary.  
}  
   
// or  
catch let error as NSError where error._domain == AVFoundationErrorDomain && error._code == AVFoundationErrorDomain.diskFull.rawValue {  
// okay: userInfo is finally accessible, but still weakly typed  
}  
   
// And in usage:  
catch let error as NSError where error._domain = AVFoundationErrorDomain {  
if let time = error.userInfo[AVErrorTimeKey] as? CMTime {  
// ...  
}  
}  
   
// After  
catch let error as AVError {  
if let time = error.time {  
// ...  
}  
}  

 

学习更多的关于这个变化,请点击这里

nulTerminatedUTF8CString 重命名为utf8CString

学习更多的关于这个变化,请点击这里

移除了字符串的UnicodeScalar重复的初始化方法

学习更多的关于这个变化,请点击这里

Failable UnicodeScalar初始化现在返回的是可选类型

学习更多的关于这个变化,请点击这里

元组不在撒泼

// No longer allowed
func foo(a: Int, b: Int) {}  
let x = (1, b: 2)  
foo(x)  

学习更多的关于这个变化,请点击这里

 

没有了currying func声明的语法

// Before:
func curried(x: Int)(y: String) -> Float {  
return Float(x) + Float(y)!  
}  
   
// After:  
func curried(x: Int) -> (String) -> Float {  
return {(y: String) -> Float in  
return Float(x) + Float(y)!  
}  
}  

学习更多的关于这个变化,请点击这里

 

上面已经列举了所以的Swift3的变化?

显然不是。

这里还有一些意见仍然在省查中,些许意见已经被推迟到3.x。我也选择了一些我认为非常小的不包括在一些附加或者改变。像removal和merger这些不经常使用的API

此外,我还没有必要更深层次的研究任何一个变化,而是对于每一个变化选择一些更高层次的审查。

有一些变化会在他们的范围内发生连锁反应。如果你对这个特殊的变化感兴趣的话,你应该看看SwiftEVO工程

Changes under active review / awaiting review for this release

  1. Add sequence-based initializers and merge methods to Dictionary
  2. Allow using optional binding to upgrade self from a weak to strong reference
  3. Add AnyHashable to standard library

Changes deferred to a 3.x release

  1. Rotate algorithm
  2. Removal of .self
  3. Allow Swift types to provide custom Obj-C representations
  4. Remove bridging conversion behavior from dynamic casts
  5. Rationalizing sequence end-operation names

Bonus:

Things I’m sure we’re all glad were rejected:

  1. Removal of where from the Swift language
  2. Require self to access instance members
  3. Removal of access modifiers from extensions

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!