由于
Swift是開源的,所以關于這門語言所有的更新內(nèi)容可以從GitHub上找到詳細的解釋。這是相關的內(nèi)容更新
Swift 3改變可以分為兩個大的部分
- 1.移除在
Swift 2.2中棄用的方法 - 2.語言更加安全,優(yōu)雅(正確的廢話)
++和--操作符
自增自減操作符是從C搬過來的,非??旖輥碓黾踊蛘邷p少1.
var i = 0
i++
++i
i--
--i
對于初學者而言可能有些奇怪,所以被移除了。使用+=或者-=來賦值操作。當然也可以通過操作符重載來實現(xiàn)上訴的功能。
var i = 0
i += 1
i -= 1
C與語言風格的循環(huán)已經(jīng)成為歷史
大多數(shù)語言都是使用C語言風格的操作符來表示循環(huán)。移除這個操作意味著以后就不能用了。因為用for-in操作完全可以替代的。
以前可以寫:
for (i = 1; i <= 10; i++) {
print(i)
}
在Swift3中,不允許這樣的寫法,用...表示的范圍
for i in 1...10 {
print(i)
}
你也可以用閉包和快捷參數(shù)來使用for-each
for i in 1...10 {
print(i)
}
移除方法參數(shù)的var聲明
方法參數(shù)通常被定義為常量,因為不需要在函數(shù)內(nèi)部修改它,然后有些情況下當把聲明作為變量的時候可能會更加方便。在Swift2中,可以通過關鍵字var標記一個方法參數(shù)作為變量,一旦方法參數(shù)用var修飾,將會創(chuàng)建一份對于參數(shù)的Copy。所以你可以在函數(shù)內(nèi)部修改它的值。
下面一個例子,用于求兩個數(shù)的最大公約數(shù):
func gcd(var a: Int, var b: Int) -> Int {
if (a == b) {
return a
}
repeat {
if (a > b) {
a = a - b
} else {
b = b - a
}
} while (a != b)
return a
}
算法比較簡單,
在Swift3中不運行設置方法參數(shù)作為變量,因為Swift開發(fā)者可能會因為var和inout而標的疑惑。所以最新的版本移除了方法參數(shù)中的var
因此,用Swift3中的語法,達到這樣的目的需要用不同的方法,比如需要去保存方法參數(shù)作為本丟變量。
func gcd(a: Int, b: Int) -> Int {
if (a == b) {
return a
}
var c = a
var d = b
repeat {
if (c > d) {
c = c - d
} else {
d = d - c
}
} while (c != d)
return c
}
擴展方法參數(shù)的形式
方法參數(shù)列表是以元組的形式,所以可以使用元組來調(diào)用函數(shù),只要元組的結構和方法參數(shù)的結構一樣,用gcd()做一個例子。
gcd(8, b: 12)可以這樣調(diào)用
或者可以
let number = (8, b: 12)
gcd(number)
正如你所見,你不需要給第一個參數(shù)具體化在Swift2,然后你不得不在調(diào)用方法的時候具體化第二個參數(shù)。
這樣的語法對于初學者而言具有迷惑性,所以使用標準的形式,在Swift3中,如下調(diào)用:
gcd(a: 8, b: 12)
你不得不給第一個參數(shù)精確地修飾符,如果不這樣做,Xcode 8直接就會報錯。
可能看到這樣的改變,會覺得那我以前的代碼如何兼容呢,為了兼容以前的,蘋果推出一種方式來解決。如下:
func gcd(_ a: Int, b: Int) -> Int {
...
}
這樣改變了方法名稱之后,就能兼容之前調(diào)用的方式了。
Seletors 作為字符串不在起作用
常見的我們在創(chuàng)建一個button之后,然后會給它加上點擊事件,比如:
//1
import UIKit
import XCPlayground
// 2
class Responder: NSObject {
func tap() {
print("Button pressed")
}
}
let responder = Responder()
// 3
let button = UIButton(type: .System)
button.setTitle("Button", forState: .Normal)
button.addTarget(responder, action: "tap", forControlEvents: .TouchUpInside)
button.sizeToFit()
button.center = CGPoint(x: 50, y: 25)
// 4
let frame = CGRect(x: 0, y: 0, width: 100, height: 50)
let view = UIView(frame: frame)
view.addSubview(button)
XCPlaygroundPage.currentPage.liveView = view
重點看一下button.addTarget(responder, action: "tap", forControlEvents: .TouchUpInside)這句話,button的selector是字符串,如果寫的類型錯了,能夠編譯通過,但是會在運行的時候崩潰。因為沒有可以響應的方法。
為了解決這個潛在的問題,Swift3用#selector()關鍵字替換了字符串類型的selectors。這種方式可以讓編譯器在編譯的時候,如果不存在這樣的方法名就能直接報出編譯錯誤,代碼如下:
btton.addTarget(responder, action: #selector(Responder.tap), for: .touchUpInside)
Key-paths 作為字符串
和Seletors作為字符串不在起作用類似,只不過將這種特性運用到了KVC(鍵值編碼)和KVO(觀察者):
之前的方式:
class Person: NSObject {
var name: String = ""
init(name: String) {
self.name = name
}
}
let me = Person(name: "Cosmin")
me.valueForKeyPath("name")
如果me.valueForKeyPath("name")中不存在屬性name,運行到這段代碼必將崩潰。
在Swift3中就不用擔心,Key-Path已經(jīng)用#keyPath()代替。
如下:
class Person: NSObject {
var name: String = ""
init(name: String) {
self.name = name
}
}
let me = Person(name: "Cosmin")
me.value(forKeyPath: #keyPath(Person.name))
從Foundation類型中去掉NS前綴
提及NS前綴,大家應該知道是Next-Step的縮寫吧。但是Swift畢竟是一門嶄新的語言,所以從前綴上就能之前的習慣做了區(qū)分??梢钥闯?,這也是未來Swift會大行其道的預兆。
比如之前:
let file = NSBundle.mainBundle().pathForResource("tutorials", ofType: "json")
let url = NSURL(fileURLWithPath: file!)
let data = NSData(contentsOfURL: url)
let json = try! NSJSONSerialization.JSONObjectWithData(data!, options: [])
print(json)
通過Foundation中的類從文件中讀取json數(shù)據(jù),中間用到了NSBundle -> NSURL -> NSData -> NSJSONSerialization.
在Swift3中,前綴被移除,看起來更加優(yōu)雅
let file = Bundle.main().pathForResource("tutorials", ofType: "json")
let url = URL(fileURLWithPath: file!)
let data = try! Data(contentsOf: url)
let json = try! JSONSerialization.jsonObject(with: data)
print(json)
純手寫碼字有點累,下面還是直接給代碼。
M_PI vs .pi
- 之前
let r = 3.0
let circumference = 2 * M_PI * r
let area = M_PI * r * r
之前是使用M_PI指代pi常量,Swift3中分別在Float,Double,CGFloat幾種類型中指代了pi常量。
- 之后
let r = 3.0
let circumference = 2 * Double.pi * r
let area = Double.pi * r * r
GCD
- 之前
let queue = dispatch_queue_create("Swift 2.2", nil)
dispatch_async(queue) {
print("Swift 2.2 queue")
}
- 之后(通過對象的方式調(diào)用)
let queue = DispatchQueue(label: "Swift 3")
queue.async {
print("Swift 3 queue")
}
枚舉
Swift3中將枚舉case看起來像屬性,所以使用小寫的方式表示了系統(tǒng)的而一些枚舉值:
比如:
.System becomes .system
.TouchUpInside becomes .touchUpInside
.FillStroke becomes .fillStroke
.CGColor becomes .cgColor
關鍵字@discardableResult
在Swift3中,如果沒有使用方法的返回值,會報出警告。如下:

使用@discardableResult關鍵字取消警告
override func viewDidLoad() {
super.viewDidLoad()
printMessage(message: "Hello Swift 3!")
}
@discardableResult
func printMessage(message: String) -> String {
let outputMessage = "Output : \(message)"
print(outputMessage)
return outputMessage
}
寫在最后
還有一些特性,需要大家自己去看看,用代碼實踐一下,效果會更好。邊寫邊想,還是有點累。尤其是找到合適的例子。