要學習Swift這門語言,就必須先了解Swift的關鍵字及對應的解釋。這里就列一下在Swift中常用到的關鍵字。
關鍵字是類似於標識符的保留字符序列,除非用重音符號(`)將其括起來,否則不能用作標識符。關鍵字是對編譯器具有特殊意義的預定義保留標識符。常見的關鍵字有以下4種。
與聲明有關的關鍵字:class、deinit、enum、extension、func、import、init、let、protocol、static、struct、subscript、typealias和var。
與語句有關的關鍵字:break、case、continue、default、do、else、fallthrough、if、in、for、return、switch、where和while。
表達式和類型關鍵字:as、dynamicType、is、new、super、self、Self、Type、__COLUMN__、__FILE__、__FUNCTION__和__LINE__。
在特定上下文中使用的關鍵字:associativity、didSet、get、infix、inout、left、mutating、none、nonmutating、operator、override、postfix、precedence、prefix、rightset、unowned、unowned(safe)、unowned(unsafe)、weak和willSet。
常見關鍵字的介紹:
1、class
在Swift當中, 我們使用Class關鍵字去聲明一個類和聲明類方法, 比如:
class Person { // 給方法添加class關鍵字表示類方法 class func work() { print("Type Method: Person: 學生.") } }
這樣我們就聲明了一個Student類。
2、let
Swift里用let修飾的變量會是一個不可變的常量,即我們不可以對它進行修改。(注意:我們用let修飾的常量是一個類, 我們可以對其所在的屬性進行修改)比如:
class Student { let name = "xiaoMing" var age = 16 var height = 160 } let studen = Student(); studen.age += 2 print("student age is \(studen.age)") //輸出結果為student age is 18
在Student類里name是不可變的,如果要對它進行修改就要將let改為var。注意:如果這個時候, 再聲明一個Student常量去引用student, 那么studen1所指向的內存塊是和studen相同的.
3、var
Swift中用var修飾的變量是一個可變的變量,即可以對它進行修改。注意:我們不會用var去引用一個類, 也沒有必要。比如:
class Student { let name = "xiaoMing" var age = 16 var height = 160 } let studen = Student(); studen.age += 2 var student2 = studen; student2.age -= 3 print("student age is \(studen.age)") print("student2 age is \(student2.age)") /** 輸出結果為 student age is 15 student2 age is 15 */
由輸出結果可以看出他們所指向的內存塊都是同一個。
4、struct
在Swift中, 我們使用struct關鍵字去聲明結構體,Swift中的結構體並不復雜,與C語言的結構體相比,除了成員變量,還多了成員方法。使得它更加接近於一個類。個人認為可以理解為是類的一個輕量化實現。比如:
struct Person { var name:String var age:Int func introduce(){ print("我叫:\(name),今年\(age)歲") } } var person = Person(name: "xiaoMing",age: 20) person.name = "xiaoMing" print("person.name = \(person.name)") person.introduce() /** 輸出結果為: person.name = xiaoMing 我叫:xiaoMing,今年20歲 */
語法與C語言或者OC類似,Swift中的結構體,在定義成員變量時一定要注明類型。另外要注意一下的是,結構體屬於值類型,而Swift中的類屬於引用類型。他們在內存管理方面會有不同。
5.enum
在Swift中, 我們使用enum關鍵字去聲明枚舉。枚舉是一種常見的數據類型,他的主要功能就是將某一種有固定數量可能性的變量的值,以一組命名過的常數來指代。比如正常情況下方向有四種可能,東,南,西,北。我們就可以聲明一組常量來指代方向的四種可能。使用枚舉可以防止用戶使用無效值,同時該變量可以使代碼更加清晰。比如:
enum Orientation:Int{ case East case South case West case North } /** 或者 enum Orientation:Int{ case East,South,West,North } */ print(Orientation.East.rawValue) /** 輸出結果 0 */
注意:我們在定義枚舉時,一定要指定類型,否則在使用時就會報錯。枚舉類型的值如果沒有賦值,他就按照默認的走,可以賦予我們自己想要的值。
6、final
Swift中,final關鍵字可以在class、func和var前修飾。表示 不可重寫 可以將類或者類中的部分實現保護起來,從而避免子類破壞。詳細了解可以去看看(Swift - final關鍵字的介紹,以及使用場景
)。比如:
class Fruit { //修飾詞 final 表示 不可重寫 可以將類或者類中的部分實現保護起來,從而避免子類破壞 final func price(){ print("price") } } class Apple : Fruit {//類繼承 // //重寫父類方法 // override func price() { // print("重寫父類的price 方法") // } }
這里重寫 price()這個函數就會報錯。
7、override
在Swift中, 如果我們要重寫某個方法, 或者某個屬性的話, 我們需要在重寫的變量前增加一個override關鍵字, 比如:
class Fruit { var sellPrice : Double = 0 func info() -> () { print("fruit") } //修飾詞 final 表示 不可重寫 可以將類或者類中的部分實現保護起來,從而避免子類破壞 final func price(){ print("price") } } class Apple : Fruit {//類繼承 func eat () -> () { print("apple22222") } //重寫父類方法 override func info() { print("重寫父類的info 方法00000") } //重寫父類的屬性 重寫父類的屬性或者方法要使用關鍵字 override 進行修飾 override var sellPrice: Double { get { print("kkkkkkk\(super.sellPrice)") return super.sellPrice + 3 } set { print("qqqqq") super.sellPrice = newValue * newValue } } } let app = Apple() app.info() app.sellPrice = 20.0 let adb = app.sellPrice print("adb == \(adb)") /** 輸出結果為: 重寫父類的info 方法00000 qqqqq kkkkkkk400.0 adb == 403.0 */
8、subscript
在Swft中,subscript關鍵字表示下標,可以讓class、struct、以及enum使用下標訪問內部的值。其實就可以快捷方式的設置或者獲取對應的屬性, 而不需要調用對應的方法去獲取或者存儲, 比如官網的一個實例:
struct Matrix { let rows: Int, columns: Int var grid: [Double] init(rows: Int, columns: Int) { self.rows = rows self.columns = columns grid = Array(repeating: 0.0, count: rows * columns) } func indexIsValid(row: Int, column: Int) -> Bool { return row >= 0 && row < rows && column >= 0 && column < columns } subscript(row: Int, column: Int) -> Double { get { assert(indexIsValid(row: row, column: column), "Index out of range") return grid[(row * columns) + column] } set { assert(indexIsValid(row: row, column: column), "Index out of range") grid[(row * columns) + column] = newValue } } } var matrix = Matrix(rows: 2, columns: 2) matrix[0, 1] = 1.5 matrix[1, 0] = 3.2 print("matrix == \(matrix)") /** 打印結果: matrix == Matrix(rows: 2, columns: 2, grid: [0.0, 1.5, 3.2000000000000002, 0.0]) */
9、static
Swift中,用static關鍵字聲明靜態變量或者函數,它保證在對應的作用域當中只有一份, 同時也不需要依賴實例化。注意:(用static關鍵字指定的方法是類方法,他是不能被子類重寫的
)比如:
class Person { // 給方法添加class關鍵字表示創建類方法 class func work() { print("Type Method: Person: 學生.") } // 使用static關鍵字創建類方法 static func ageOfPerson(name: String) { print("Type Method: Person name: \(name)") } // 可以和類方法重名, 以及一樣的參數. func nameOfPerson(name: String) { print("Instance Method: person name \(name)") } } class Student: Person { //注意 子類Student的實例方法work(), 和父類的類方法work()沒有關系, 二者不在同一個級別上, 不存在同名問題. func work() { print("Instance Method: Student: University Student") } }
10、mutating
Swift中,mutating關鍵字指的是可變即可修改。用在structure和enumeration中,雖然結構體和枚舉可以定義自己的方法,但是默認情況下,實例方法中是不可以修改值類型的屬性。為了能夠在實例方法中修改屬性值,可以在方法定義前添加關鍵字mutating。比如:
struct rect { var width = 0,height = 0 mutating func changeRect(x:Int, y:Int) { self.width += x self.height += y } } enum Direction { case Top, Left, Right, Bottom mutating func lookDirection() { switch self { case .Top: self = .Top case .Left: self = .Left case .Right: self = .Right case .Bottom: self = .Bottom } print("self === \(self)") } } var re = rect(width: 5, height: 5) re.changeRect(x: 32, y: 15) print("re = \(re)") /** 打印結果為:re = rect(width: 37, height: 20) */ var dir = Direction.Left dir.lookDirection() /** 打印結果為:self === Left */
11、typealias
在Swift中,使用關鍵字typealias定義類型別名(typealias就相當於objective-c中的typedef),就是將類型重命名,看起來更加語義化。比如:
typealias Width = CGFloat typealias Height = CGFloat func rectangularArea(width:Width, height:Height) -> Double { return Double(width*height) } let area: Double = rectangularArea(width: 10, height: 20) print(area) /** 結果為:200.0 */
12、lazy
在Swift中,lazy關鍵修飾的變量, 只有在第一次被調用的時候才會去初始化值(即懶加載)。比如:
lazy var first = NSArray(objects: "1","2")
注意:用lazy修飾的變量必須是用var聲明的, 因為屬性的初始值可能在實例構造完成之后才會得到。而常量屬性在構造過程完成之前必須要有初始值,因此無法聲明成延遲屬性。如果被lazy修飾的變量沒有在初始化時就被多個線程調用, 那就沒有辦法保證它只被初始化一次了。
13、init
在Swift 中,init關鍵字也表示構造器。比如:
class PerSon { var name:String init?(name : String) { if name.isEmpty { return nil } self.name = name } } let person = PerSon.init(name: "xiaoQiang") print("person is name \(String(describing: person?.name))") /** 打印結果為:person is name Optional("xiaoQiang") */
在例子里在init后面加個”?”號, 表明該構造器可以允許失敗。
14、required
在Swift里,required是用來修飾init方法的,說明該構造方法是必須實現的。比如:
class PerSon { var name:String required init(name : String) { self.name = name } } class Student: PerSon { required init(name:String) { super.init(name: name) } }
從上面的代碼示例中不難看出,如果子類需要添加異於父類的初始化方法時,必須先要實現父類中使用required
修飾符修飾過的初始化方法,並且也要使用required
修飾符而不是override
。
注意: (1)required
修飾符只能用於修飾類初始化方法。
(2)當子類含有異於父類的初始化方法時(初始化方法參數類型和數量異於父類),子類必須要實現父類的required
初始化方法,並且也要使用required
修飾符而不是override
。
(3)當子類沒有初始化方法時,可以不用實現父類的required
初始化方法。
15、extension
在swift中,extension與Objective-C的category有點類似,但是extension比起category來說更加強大和靈活,它不僅可以擴展某種類型或結構體的方法,同時它還可以與protocol等結合使用,編寫出更加靈活和強大的代碼。它可以為特定的class, strut, enum或者protocol添加新的特性。當你沒有權限對源代碼進行改造的時候,此時可以通過extension來對類型進行擴展。extension有點類似於OC的類別 -- category,但稍微不同的是category有名字,而extension沒有名字。在Swift 中的可以擴展以下幾個:
(1)定義實例方法和類型方法
(2)添加計算型屬性和計算靜態屬性
(3)定義下標
(4)提供新的構造器
(5)定義和使用新的嵌套類型
(6)使一個已有類型符合某個接口
比如:
// 添加計算屬性 extension Double { var km: Double { return self * 1_000.0 } var m: Double { return self } var cm: Double { return self / 100.0 } } class Person { var name:String var age:Int = 0 init?(name:String) { if name.isEmpty { return nil } self.name = name } } extension Person { //添加方法 func run() { print("走了50公里") } } let oneInch = 25.4.km print("One inch is \(oneInch) meters") /** 輸出結果:One inch is 25400.0 meters */ let person = Person.init(name: "xiaom") person?.run() /** 輸出結果:走了50公里 */
想要了解詳情可以去看看這篇文漲(apple documents - extensions)
16、convenient
swift中,使用convenience修飾的構造函數叫做便利構造函數 。便利構造函數通常用在對系統的類進行構造函數的擴充時使用。便利構造函數有如下幾個特點:
(1)便利構造函數通常都是寫在extension里面
(2)便利函數init前面需要加載convenience
(3)在便利構造函數中需要明確的調用self.init()
比如:
extension UIButton{ //swit中類方法是以class開頭的方法,類似於oc中+開頭的方法 class func createButton(imageName:String)->UIButton{ let btn=UIButton() btn.setImage(UIImage(named:imageName), for: .normal) btn.sizeToFit() return btn } /* convenience:便利,使用convenience修飾的構造函數叫做便利構造函數 便利構造函數通常用在對系統的類進行構造函數的擴充時使用。 */ convenience init(imageName:String,bgImageName:String){ self.init() if !imageName.isEmpty { setImage(UIImage(named:imageName), for: .normal) } if !imageName.isEmpty { setBackgroundImage(UIImage(named:bgImageName), for: .normal) } sizeToFit() } } let btn = UIButton.init(imageName: "huanying", bgImageName: "") btn.frame = CGRect.init(x: 10, y: 120, width: 100, height: 30) btn.backgroundColor = UIColor.red self.view.addSubview(btn)
17、deinit
在Swift中,deinit屬於析構函數,當對象結束其生命周期時(例如對象所在的函數已調用完畢),系統自動執行析構函數。和OC中的dealloc 一樣的,通常在deinit和dealloc中需要執行的操作有:
(1)對象銷毀
(2)KVO移除
(3)移除通知
(4)NSTimer銷毀
18、fallthrough
swift語言特性switch語句的break可以忽略不寫,滿足條件時直接跳出循環.fallthrough的作用就是執行完當前case,繼續執行下面的case.類似於其它語言中省去break里,會繼續往后一個case跑,直到碰到break或default才完成的效果。比如:
var myClass = MyClass(parm: 9) let index = 15 switch index { case 1 : print( "index is 100") case 10,15 : print( "index is either 10 or 15") case 5 : print( "index is 5") default : print( "default case") } /** 輸出結果:index is either 10 or 15 */ let index = 15 switch index { case 100 : print( "index is 100") fallthrough case 10,15 : print( "index is either 10 or 15") fallthrough case 5 : print( "index is 5") default : print( "default case") } /** 打印結果: index is either 10 or 15 index is 5 */
19、protocol
在Swift中,protocol關鍵字也是屬於協議。比如:
protocol PersonProtocol { var height: Int { get set } var weight: Int { get } func getName() func getSex() func getAge(age: Int) } struct Student: PersonProtocol { var height = 178 var weight = 120 func getName() { print("MelodyZhy") } func getSex() { print("boy") } func getAge(age: Int) { print("age = \(age)") } } var stu = Student() let height1 = stu.height stu.height = 180 print("height1 = \(height1) height2 = \(stu.height)") /** 輸出結果: height1 = 178 height2 = 180 */
20、open
在Swift中,open修飾的對象表示可以被任何人使用,包括override和繼承。例如:
import UIKit // 在本類外的范圍外可以被繼承 open class ParentClass1: NSObject { // 這個方法在任何地方都可以被override open func abc() { print("abc") } }class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() //這里可以調用module1的方法 let child = ChildrenClass1.init() child.abc() /** 打印結果:abc */ } class ChildrenClass1: ParentClass1 { } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }
21、public
在Swift中,public表示公有訪問權限,類或者類的公有屬性或者公有方法可以從文件或者模塊的任何地方進行訪問。但在其他模塊(一個App就是一個模塊,一個第三方API, 第三等方框架等都是一個完整的模塊)不可以被override和繼承,而在本模塊內可以被override和繼承。
import UIKit // 在module1外的范圍外可以被繼承 public class ParentClass1: NSObject { // 這個方法在任何地方都可以被override public func abc() { print("abc") } }class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() //這里可以調用module1的方法 let child = ChildrenClass1.init() child.abc() /** 打印結果:abc11 */ } class ChildrenClass1: ParentClass1 { override func abc() { print("abc11") } func run() -> Void { print("run") } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }
22、internal
在Swift中,public表示內部的訪問權限。即有着internal訪問權限的屬性和方法說明在模塊內部可以訪問,超出模塊內部就不可被訪問了。在Swift中默認就是internal的訪問權限。
import UIKit // 在module1外的范圍外可以被繼承 internal class ParentClass1: NSObject { // 這個方法在任何地方都可以被override func abc() { print("abc") } } class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() //這里可以調用module1的方法 let child = ChildrenClass1.init() child.abc() /** 打印結果:abc11 */ } class ChildrenClass1: ParentClass1 { override func abc() { print("abc11") } func run() -> Void { print("run") } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }
23、private
在Swift中,private私有訪問權限。被private修飾的類或者類的屬性或方法可以在同一個物理文件中訪問。如果超出該物理文件,那么有着private訪問權限的屬性和方法就不能被訪問。比如:
import UIKit // 在module1外的范圍外可以被繼承 internal class ParentClass1: NSObject { // 這個方法在任何地方都可以被override private func abc() { print("abc") } } class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() //這里可以調用module1的方法 let child = ChildrenClass1.init() child.abc() /** 打印結果:abc11 */ } class ChildrenClass1: ParentClass1 { /** 這里就會報錯 */ override func abc() { print("abc11") } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }
24、fileprivate
在Swift中,fileprivate訪問級別所修飾的屬性或者方法在當前的Swift源文件里可以訪問。比如:
import UIKit // 在module1外的范圍外可以被繼承 internal class ParentClass1: NSObject { // 這個方法在任何地方都可以被override fileprivate func abc() { print("abc") } } class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() //這里可以調用module1的方法 let child = ChildrenClass1.init() child.abc() /** 打印結果:abc11 */ } class ChildrenClass1: ParentClass1 { override func abc() { print("abc11") } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }
說明:5種修飾符訪問權限排序open> public > interal > fileprivate > private。
參考文獻:
http://www.jianshu.com/p/6daa3e309235