Swift 3.0 【Swift 3.0 相较于 Swift 2.2 的变化】

1、编译器和语法变化

函数或方法参数

调用函数或方法时从第一个参数开始就必须指定参数名

在Swift的历史版本中出现过在调用函数时不须要指定任何函数参数(或者从第二个参数开始指定参数名),在调用方法时则必须从第二个参数开始必须指定参数名等多种状况,而在Swift3.0中不论是函数仍是方法都必须从第一个参数开始必须指定参数名(固然可使用“_”明确指出调用时省略参数)。

// 从第一个参数就必须指定参数名,除非使用"_"明确指出省略参数
func sum(num1:Int,num2:Int)->Int{
    return num1 + num2
}

sum(num1: 1, num2: 2) // old: sum(1,2)或者sum(1, num2: 2)

取消var参数

//func increase(var a:Int){
//    a += 1
//}
// 上面的代码会报错,可改写成
func increase(a:Int){
    var a = a
    a += 1
}

inout参数修饰改放到类型前

//func increase(inout a:Int) {
//    a += 1
//}
// 上面的代码会报错,可改成
func increase( a:inout Int) {
    a += 1
}

 

方法返回值

Swift 3.0 中方法的返回值必须有接收不然会报警告,固然其实主要目的是为了不开发人员忘记接收返回值的状况,可是有些状况下确实不须要使用返回值可使用"_"接收来忽略返回值。固然你也能够增长@discardableResult声明,告诉编译器此方法能够不用接收返回值。

struct Caculator {
    func sum(a:Int,b:Int) -> Int {
        return a + b
    }
    
    @discardableResult
    func func1(a:Int,b:Int) ->Int {
        return a - b + 1
    }
}
let ca = Caculator()
ca.sum(a: 1, b: 2) // 此处会警告,由于方法有返回值可是没有接收
let _ = ca.sum(a: 1, b: 2) // 使用"_"接收无用返回值
ca.func1(a: 1, b: 2) // 因为func1添加了@discardableResult声明,即便不接收返回值也不会警告

 

可选类型

Swift3.0对于可选类型控制更加严谨,隐式可选类型和其余类型的运算以后得到的是可选类型而不是隐式可选类型。

let a:Int! = 1
let b = a + 1 // 此时强制解包,b是Int型
let c = a // 注意此时c是Int? 在以前的Swift版本中c是Int!

 

Selector的变化

Selector的改变其实从1.0到3.0经历了屡次变化,从最先的@Selector("method:")到如今的#selector(method(param1:))能够说经历了屡次修改,好在它变得愈来愈好,毕竟字符串操做对于语法检查来讲是很无助的。

class MyClass { @objc func sum(a:Int,b:Int) -> Int { return a + b } func func1(){ let _ = #selector(sum(a:b:)) } } // old: Swift 2.2 //class MyClass { // @objc func sum(a:Int,b:Int) -> Int { // return a + b // } // // func func1(){ // let _ = #selector(sum(_:b:)) // } //}class MyClass { @objc func sum(a:Int,b:Int) -> Int { return a + b } func func1(){ let _ = #selector(sum(a:b:)) } } // old: Swift 2.2 //class MyClass { // @objc func sum(a:Int,b:Int) -> Int { // return a + b // } // // func func1(){ // let _ = #selector(sum(_:b:)) // } //}class MyClass { @objc func sum(a:Int,b:Int) -> Int { return a + b } func func1(){ let _ = #selector(sum(a:b:)) } } // old: Swift 2.2 //class MyClass { // @objc func sum(a:Int,b:Int) -> Int { // return a + b // } // // func func1(){ // let _ = #selector(sum(_:b:)) // } //}

 

协议中的可选方法

在Swift3.0以前若是要定义协议中可选方法,只须要给协议加上@objc以后方法使用optional修饰就能够了,可是Swift3.0中除了协议须要@objc修饰,可选方法也必须使用@objc来修饰。

@objc protocol MyProtocol { @objc optional func func1() //old: optional func func1() func func2() }@objc protocol MyProtocol { @objc optional func func1() //old: optional func func1() func func2() }@objc protocol MyProtocol { @objc optional func func1() //old: optional func func1() func func2() }

 

取消++、--操做符

var d = 1 d++ //报错,能够改写成 d += 1 或者 d = d + 1var d = 1 d++ //报错,能够改写成 d += 1 或者 d = d + 1var d = 1 d++ //报错,能够改写成 d += 1 或者 d = d + 1

 

取消C风格for循环

//for var i = 0 ;i < 10 ; i += 1 { // debugPrint(i) //} // 上面的代码会报错,可改写成以下代码 for i in 0 ..< 10 { debugPrint(i) }//for var i = 0 ;i < 10 ; i += 1 { // debugPrint(i) //} // 上面的代码会报错,可改写成以下代码 for i in 0 ..< 10 { debugPrint(i) }//for var i = 0 ;i < 10 ; i += 1 { // debugPrint(i) //} // 上面的代码会报错,可改写成以下代码 for i in 0 ..< 10 { debugPrint(i) }

 

 

2、SDK类库变化

你们都知道Swift诞生在Objective-C已经发展的至关成熟的状况下,为了保证ObjC开发人员顺利过渡到Swift,也由于Swift处于初级阶段,不少类库和方法命名都尽可能和ObjC保持一致,在使用Swift开发iOS应用中到处能够看到ObjC的影子。可是做为一门Modern语言Swift仍是作出了改变,从中能够看出往后Swift将完全摆脱ObjC的影子。这其中包括从新导入Foundation消除类型前缀、方法名去重、函数和方法去C风格等等。

命名

// 1.去掉前缀 let url1 = URL(string: "www.cmjstudio.com") let isFileURL = url1?.isFileURL //old:url1.fileURL ,如今更加注重语意 let data1 = Data() //NSData // 2.方法名使用动词,其余名词、介词等做为参数或移除 var array1 = [1,2,3] array1.append(contentsOf: [4,5,6]) // old:array1.appendContentsOf([4,5,6]) array1.remove(at: 0) // old:array1.removeAtIndex(0) // 3.不引发歧义的状况下尽可能消除重复 let color1 = UIColor.red() // old:var color1 = UIColor.redColor() // 4.枚举成员首字母变成小写 let label1 = UILabel() label1.textAlignment = .center // old:label1.textAlignment = .Center // 5.按钮的Normal状态去掉 let btn1 = UIButton() btn1.setTitle("hello", for: UIControlState()) // 至关于Normal状态// 1.去掉前缀 let url1 = URL(string: "www.cmjstudio.com") let isFileURL = url1?.isFileURL //old:url1.fileURL ,如今更加注重语意 let data1 = Data() //NSData // 2.方法名使用动词,其余名词、介词等做为参数或移除 var array1 = [1,2,3] array1.append(contentsOf: [4,5,6]) // old:array1.appendContentsOf([4,5,6]) array1.remove(at: 0) // old:array1.removeAtIndex(0) // 3.不引发歧义的状况下尽可能消除重复 let color1 = UIColor.red() // old:var color1 = UIColor.redColor() // 4.枚举成员首字母变成小写 let label1 = UILabel() label1.textAlignment = .center // old:label1.textAlignment = .Center // 5.按钮的Normal状态去掉 let btn1 = UIButton() btn1.setTitle("hello", for: UIControlState()) // 至关于Normal状态// 1.去掉前缀 let url1 = URL(string: "www.cmjstudio.com") let isFileURL = url1?.isFileURL //old:url1.fileURL ,如今更加注重语意 let data1 = Data() //NSData // 2.方法名使用动词,其余名词、介词等做为参数或移除 var array1 = [1,2,3] array1.append(contentsOf: [4,5,6]) // old:array1.appendContentsOf([4,5,6]) array1.remove(at: 0) // old:array1.removeAtIndex(0) // 3.不引发歧义的状况下尽可能消除重复 let color1 = UIColor.red() // old:var color1 = UIColor.redColor() // 4.枚举成员首字母变成小写 let label1 = UILabel() label1.textAlignment = .center // old:label1.textAlignment = .Center // 5.按钮的Normal状态去掉 let btn1 = UIButton() btn1.setTitle("hello", for: UIControlState()) // 至关于Normal状态

 

去C风格

Swift发展初期不少类库的引入依然保持的ObjC风格,可是ObjC因为根出C语言,所以不少操做其实并非对象和方法操做而是C语言的函数形式。到了Swift3.0以后这一现状将发生变化,全局函数将会变成某些类型的方法;某些常量定义将以某个枚举类型的成员来表示。

let rect1 = CGRect(x: 0, y: 0, width: 100, height: 100) // 下面的代码将要报错,3.0彻底废除这种类C的风格 //let rect1 = CGRectMake(0, 0, 100, 100) if let context1 = UIGraphicsGetCurrentContext() { CGContext.fillPath(context1) // old:CGContextFillPath(context1!) } // GCD的改变 let queue = DispatchQueue(label: "myqueue") queue.async { debugPrint("hello world!") } // old: //let queue = dispatch_queue_create("myqueue", nil) //dispatch_async(queue) { // debugPrint("hello world!") //} // 相关常量定义被移到枚举内部 NotificationCenter.defaultCenter().addObserver(self, selector: #selector(userDefaultChange()), name: UserDefaults.didChangeNotification, object: nil) //old:NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(userDefaultChange()), name: NSUserDefaultsDidChangeNotification, object: nil)let rect1 = CGRect(x: 0, y: 0, width: 100, height: 100) // 下面的代码将要报错,3.0彻底废除这种类C的风格 //let rect1 = CGRectMake(0, 0, 100, 100) if let context1 = UIGraphicsGetCurrentContext() { CGContext.fillPath(context1) // old:CGContextFillPath(context1!) } // GCD的改变 let queue = DispatchQueue(label: "myqueue") queue.async { debugPrint("hello world!") } // old: //let queue = dispatch_queue_create("myqueue", nil) //dispatch_async(queue) { // debugPrint("hello world!") //} // 相关常量定义被移到枚举内部 NotificationCenter.defaultCenter().addObserver(self, selector: #selector(userDefaultChange()), name: UserDefaults.didChangeNotification, object: nil) //old:NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(userDefaultChange()), name: NSUserDefaultsDidChangeNotification, object: nil)let rect1 = CGRect(x: 0, y: 0, width: 100, height: 100) // 下面的代码将要报错,3.0彻底废除这种类C的风格 //let rect1 = CGRectMake(0, 0, 100, 100) if let context1 = UIGraphicsGetCurrentContext() { CGContext.fillPath(context1) // old:CGContextFillPath(context1!) } // GCD的改变 let queue = DispatchQueue(label: "myqueue") queue.async { debugPrint("hello world!") } // old: //let queue = dispatch_queue_create("myqueue", nil) //dispatch_async(queue) { // debugPrint("hello world!") //} // 相关常量定义被移到枚举内部 NotificationCenter.defaultCenter().addObserver(self, selector: #selector(userDefaultChange()), name: UserDefaults.didChangeNotification, object: nil) //old:NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(userDefaultChange()), name: NSUserDefaultsDidChangeNotification, object: nil)

 

集合API的变化

let array1 = [1,2,3] let next = array1.index(after: 0) // old:let start = array1.startIndex let next = start.successor() let first = array1.first { (element) -> Bool in // 增长新的方法 element > 1 } let r = Range(0..<3) //old: let _ = NSRange(location: 0, length: 3) // 下面的代码必须在控制器中执行,用于遍历当前view及其父视图 for subview in sequence(first: self.view, next: { $0?.superview }){ debugPrint(subview) }let array1 = [1,2,3] let next = array1.index(after: 0) // old:let start = array1.startIndex let next = start.successor() let first = array1.first { (element) -> Bool in // 增长新的方法 element > 1 } let r = Range(0..<3) //old: let _ = NSRange(location: 0, length: 3) // 下面的代码必须在控制器中执行,用于遍历当前view及其父视图 for subview in sequence(first: self.view, next: { $0?.superview }){ debugPrint(subview) }let array1 = [1,2,3] let next = array1.index(after: 0) // old:let start = array1.startIndex let next = start.successor() let first = array1.first { (element) -> Bool in // 增长新的方法 element > 1 } let r = Range(0..<3) //old: let _ = NSRange(location: 0, length: 3) // 下面的代码必须在控制器中执行,用于遍历当前view及其父视图 for subview in sequence(first: self.view, next: { $0?.superview }){ debugPrint(subview) }

 

新的浮点协议

Float、Double、CGFloat使用了新的协议,提供了提供 IEEE-754标准的属性和方法。

let a = 2 * Float.pi // old: let a = 2 * M_PI let b = 2.0 * .pi // 注意前面是浮点型,后面能够省略Floatlet a = 2 * Float.pi // old: let a = 2 * M_PI let b = 2.0 * .pi // 注意前面是浮点型,后面能够省略Floatlet a = 2 * Float.pi // old: let a = 2 * M_PI let b = 2.0 * .pi // 注意前面是浮点型,后面能够省略Float

 

 

3、从Swift_2.2迁移到Swift_3.0

能够看出若是要更新到Swift3.0现有项目须要做出大量修改,通过使用以前的项目进行测试,区区十个类文件就出现了一百多个错误,不过好在Xcode 8已经提供了很好用的迁移工具(Xcode:Editor - Convert - To Current Swift Syntax),通过迁移工具转化后仅仅发现两处错误须要手动修正。在使用这个工具的时候你们会看到以下界面:

 

\

 

 

Swift 2.3?没错Swift2.2和Swift 3.0中间还有个Swift 2.3,Apple也解释了什么是Swift 2.3,其实就是Swift 2.2 + New SDKs。之因此如此是由于Xcode 8目前仍是beta版,使用Swift 3.0进行开发的应用还不能提交App Store,所以在Swift 2.2基础上使用新的SDK开发仍是有存在必要的。

 

 

Swift 2.3?没错Swift2.2和Swift 3.0中间还有个Swift 2.3,Apple也解释了什么是Swift 2.3,其实就是Swift 2.2 + New SDKs。之因此如此是由于Xcode 8目前仍是beta版,使用Swift 3.0进行开发的应用还不能提交App Store,所以在Swift 2.2基础上使用新的SDK开发仍是有存在必要的。

相关文章
相关标签/搜索