附上資料地址:w3cschool-Swift 教程 、Swift中的關鍵字詳解html
class
:聲明一個類,或者類方法class Person: NSObject {
//聲明一個實例方法
func run() {
print("run")
}
//class修飾表示:聲明一個類方法
class func work() {
print("work")
}
}
複製代碼
struct
:聲明結構體,內部能夠聲明成員變量、成員方法。所以更接近於一個類,能夠說是類的一個輕量化實現//聲明:
struct Person {
var name:String
var age:Int
func introduce(){
print("我叫:\(name),今年\(age)歲")
}
}
//調用:
var person = Person(name: "xiaoMing",age: 20)
person.introduce()
//輸出:
我叫:xiaoMing,今年20歲
複製代碼
struct
和 class
比較struct是結構體,class是類
一、struct是值類型,class是引用類型;意思是:聲明一個新的變量指向這個結構體,改變某個屬性,本來的結構體屬性不會發生變化;而類會隨着改變
`
代碼示例:
struct myStru {
var width = 200
}
class myClass {
var width = 200
}
//調用
var stu = myStru()
var stu2 = stu
stu2.width = 300
print(stu.width,stu2.width)
//200 300
var cls = myClass()
var cls2 = cls
cls2.width = 300
print(cls.width,cls2.width)
//300 300
`
二、struct不能被繼承,class能夠被繼承
三、用let修飾class對象,可以修改類的值;若要修改struct的值,要用var來修飾
四、struct是放在棧上,class是放在堆上,所以struct的訪問速度更快
五、struct裏面若是想聲明一個func來修改聲明的屬性,須要添加關鍵字mutating,才能編譯成功;而class不須要
六、全部的struct都有一個自動生成的成員構造器,而class須要本身生成
七、在struct中,成員變量能夠沒有初始值;但在class中,若是成員變量沒有初始值,就必須爲它寫一個構造函數
複製代碼
static
:聲明靜態變量或者函數,它保證在對應的做用域當中只有一份, 同時也不須要依賴實例化。若是用於修飾函數,表示類方法,且不能被重寫class Person: NSObject {
var name: String
//類方法,而且該方法不能被子類重寫
static func run() {
print(self.name + "running")
}
}
複製代碼
static
和 class
比較都是放在`func`前面用於指定類方法,只不過`static`修飾的類方法不能夠被重寫
複製代碼
typealias
:各種起別名//聲明
typealias abc = Int
//調用
let a:abc = 100
複製代碼
enum
:枚舉,一種常見的數據類型。好處:使用枚舉能夠防止用戶使用無效值,同時該變量可使代碼更加清晰。//寫法1,默認賦值0、一、二、3
enum Orientation1:Int{
case East
case South
case West
case North
}
//寫法2
enum Orientation2:Int{
case East,South,West,North
}
//調用 具體的值
print(Orientation1.East.rawValue,Orientation1.South.rawValue,Orientation2.West.rawValue,Orientation2.North.rawValue)
//打印
0 1 2 3
複製代碼
extension
:拓展,相似oc中的category
分類,可是比分類更增強大。通常用於:
//給person類添加一個run方法
class Person: NSObject {
var name = "swift"
}
extension Person{
func run() {
print(self.name + "running")
}
}
//調用
let per = Person()
per.run()
複製代碼
subscript
:下標腳本,可讓 結構體
、枚舉
、類
使用下標功能。須要注意:subscript
中能夠沒有set
方法,可是要有get
方法struct Person {
var age = 0
var no = 0
subscript(index: Int) -> Int {
set {
if index == 0 {
age = newValue
} else {
no = newValue
}
}
get {
if index == 0 {
return age
} else {
return no
}
}
}
}
var p = Person()
p[0] = 10
p[1] = 20
print(p.age) // 10
print(p[0]) // 10
print(p.no) // 20
print(p[1]) // 20
複製代碼
傳多個參數的例子:swift
class Matix {
var data = [
[0,0,0],
[0,0,0],
[0,0,0]
]
subscript(row: Int , col: Int) -> Int {
set {
//守衛,不在這個範圍以內的就return
guard row >= 0 && row < 3 && col >= 0 && col < 3 else {
return
}
data[row][col] = newValue
}
get {
guard row >= 0 && row < 3 && col >= 0 && col < 3 else {
return 0
}
return data[row][col]
}
}
}
//調用
var m = Matix()
m[1, 1] = 3
m[0, 1] = 4
//這個超出範圍,直接return了
m[4, 4] = 9
print(m.data)
//打印
[[0, 4, 0], [0, 3, 0], [0, 0, 0]]
複製代碼
init
:構造函數,初始化方法class PerSon: NSObject {
//若是不給屬性直接賦一個初始化值,就必須聲明構造函數
var name:String
init(name : String) {
self.name = name
}
}
//調用
let person = PerSon.init(name: "xiaoMing")
print(person.name)
//簡寫
let per = PerSon(name: "xiaoHong")
print(per.name)
複製代碼
deinit
:析構函數,釋放方法。與oc中的dealloc
同樣,用於:對象的銷燬、KVO移除、通知移除、NSTimer銷燬數組
protocol
:協議markdown
fallthrough
:穿透,在switch中,執行完當前case,繼續向下執行下一個case//寫法1 = 寫法2
let num = 100
//寫法1
switch num {
case 100:
fallthrough
case 200:
print("100 + 200")
default:
print("no")
}
//寫法2
switch num {
case 100,200:
print("100 + 200")
default:
print("no")
}
複製代碼
where
:篩選條件用的,適用於do-catch
、switch
、for-in
、泛型
、協議
等let array = [100,-50,36,-8,45]
//遍歷數組,只有值大於40的纔打印
for i in array where i > 40 {
print(i)
}
//打印
100
45
複製代碼
is
:類型檢查操做符,檢查一個實例是否屬於一個特定的子類,是返回true,不是返回false// 1.定義數組
let array : [Any] = [12, "zhangsan"]
// 2.取出數組中的第一個
let objcFirst = array.first!
// 3.判斷第一個元素是不是一個Int類型
if objcFirst is Int {
print("是Int類型")
} else {
print("非Int類型")
}
複製代碼
as
:類型轉換操做符,向上轉型,從派生類轉換成基類//自己根據值定義的是int類型,經過as轉換成float類型
var number = 1 as Float
print(number) //1.0
var number = 1 as Float
至關於
var number = Float(1)
複製代碼
as!
:向下轉型,轉成其子類類型,屬於強制轉型,若是轉換失敗會報錯閉包
as?
:規則跟as!
同樣,若是轉換失敗,會返回一個nil對象異步
// 1.定義數組
let array : [Any] = [12, "zhangsan"]
// 2.取出數組中最後一個元素
let objcLast = array.last!
// 3.轉成真正的類型來使用
// as? 將Any轉成可選類型,經過判斷可選類型是否有值,來決定是否轉化成功了
let name = objcLast as? String
print(name) // 結果:Optional("zhangsan")
// as! 將Any轉成具體的類型,若是不是該類型,那麼程序會崩潰
let name2 = objcLast as! String
print(name2) // 結果:zhangsan
複製代碼
convenience
:便利構造函數,用於修飾構造方法init
,一般用於對系統類的init構造方法
進行擴充,特色:async
convenience
一般寫在extension
中init
以前添加convenience
convenience
中須要明確調用self.init()
/*
對系統的init進行擴充,
而且這個方法是公共的,
若是子類要修改,就須要先實現父類方法,不能直接重寫
*/
required convenience public init(...) {
...
self.init()
...
}
複製代碼
required
:只用於修飾類的init
初始化方法,表示該初始化方法是必須實現。要求子類必須實現父類的初始化方法使用規則:ide
required init
方法,這時不能用override
,要一樣使用required
修飾required init
方法//子類異於父類init方法狀況
class PerSon: NSObject {
var name: String
//若是子類要自定義init方法,要先實現父類的
required init(name: String) {
self.name = name
}
}
class Student: PerSon {
var age: Int = 0
//先實現父類的
required init(name:String) {
super.init(name: name)
}
//再進行自定義init
init(firstName: String, age:Int) {
self.age = age
super.init(name: firstName)
}
}
複製代碼
mutating
:在結構體或者枚舉中,放在func前,表示可修改它所屬的實例及實例屬性的值。用於在內部成員方法中修改爲員變量的值//正常狀況
struct myStruct1 {
var num1 = 100
var num2 = 200
var num3 = 300
}
var stu1 = myStruct1()
print(stu1.num1)//100
//直接修改爲員變量的值
stu1.num1 = 999
print(stu1.num1)//999
//經過內部方法改變值
struct myStruct2 {
var num1 = 100
var num2 = 200
var num3 = 300
mutating func changeNum(mark:Int) {
self.num1 += mark
}
}
//調用
var stu2 = myStruct2()
print(stu2.num1)//100
//經過調用結構體的成員方法來修改爲員變量的值
stu2.changeNum(mark: 99)
print(stu2.num1)//199
複製代碼
lazy
:懶加載,修飾變量,只有在第一次調用的時候纔去初始化值lazy var first = NSArray(objects: "1","2")
複製代碼
override
:重寫父類的方法函數
final
:能夠用來修飾class
、func
、var
,表示不可重寫。能夠將類或者類中的部分實現保護起來,從而避免子類破壞oop
inout
:將值類型的對象 用 引用的方式傳遞,意思是能夠修改外部變量
func test(num: inout Int){
//若是不加inout,改變外部變量會報錯
num += 1
}
var a = 10
//調用的時候,是取地址操做
test(num: &a)
print(a)//11
複製代碼
defer
:延遲執行,修飾一段函數內任一段代碼,使其必須在函數中其餘代碼執行完畢,函數即將結束前調用;若是有多個defer
會自下而上的順序執行func test(){
print("函數開始")
defer{
print("執行defer1")
}
print("函數將結束")
defer{
print("執行defer2")
}
defer{
print("執行defer3")
}
}
//調用
test()
//打印
函數開始
函數將結束
執行defer3
執行defer2
執行defer1
複製代碼
添加異步線程的狀況
func test(){
print("函數開始")
defer{
print("執行defer1")
}
defer{
print("執行defer2")
}
DispatchQueue.main.asyncAfter(deadline: .now()+1) {
print("異步執行完畢")
}
print("函數將結束")
defer{
print("執行defer3")
}
}
test()
//打印:
函數開始
函數將結束
執行defer3
執行defer2
執行defer1
異步執行完畢
結論:
異步代碼的執行,不會影響defer的執行時間。事實上,defer的執行只和其所在的做用域有關,若是做用域即將被回收,那麼會在回收以前執行defer。
複製代碼
throws
:放在可能會出現異常或者錯誤的函數後面,會把發生的錯誤帶出來,在調用的時候進行錯誤處理,節省了維護成本;通常調用的時候會配合try
、do-catch
一塊兒使用代碼示例:
//錯誤類型枚舉
enum MyError : Error {
case ErrorOne
case ErrorTwo
case ErrorOther
}
//使用:關鍵字所在的位置
func thisFuncCouldThrowError(_ type: Int) throws -> String{
if type == 1 {
return "成功"
}else if type == 2{
throw MyError.ErrorTwo
}else{
throw MyError.ErrorOther
}
}
//調用,配合do-catch進行異常捕捉,拋出異常的方法在調用前要加 try 關鍵字
do {
let stu = try thisFuncCouldThrowError(20)
print("若是出現錯誤,這裏的代碼就不會執行了")
print(stu)
} catch let err as MyError/* 這裏若是捕捉到的錯誤,屬於自定義枚舉的值,就進行相關處理*/{
print("出現了錯誤")
print(err)
} catch {
//這裏必需要攜帶一個空的catch 否則會報錯。 緣由是可能遺漏
}
//打印
出現了錯誤
ErrorOther
複製代碼
rethrows
:異常往上傳遞的關鍵字,針對的不是函數或者方法的自己,而是它攜帶的閉包類型的參數,當它的閉包類型的參數throws的時候,咱們要使用rethrows繼續將這個異常往上傳遞, 直到被調用者使用到。這相比throws多一個傳遞的環節//throw函數做爲閉包參數傳入
//throws
func thisFuncCouldThrowError(_ type: Int) throws -> String{
if type == 1 {
return "成功"
}else if type == 2{
throw MyError.ErrorTwo
}else{
throw MyError.ErrorOther
}
}
//rethrows
func thisFuncRethrows(_ throwsError:(Int) throws -> String) rethrows{
do {
let stu = try throwsError(20)
print("若是出現錯誤,這裏的代碼就不會執行了")
print(stu)
} catch let err as MyError{
throw err //這裏進行了 再次throw
} catch{
}
}
//調用
let afunc = self.thisFuncCouldThrowError
do {
try self.thisFuncRethrows(afunc)
print("沒有錯誤,若是出現錯誤,這裏的代碼就不會執行了")
} catch let err as MyError {
print("出現了錯誤")
print(err)
}catch{
//這裏必需要攜帶一個空的catch 否則會報錯。 緣由是可能遺漏
}
複製代碼
swift中提供了5種訪問控制的權限: 由低到高:private
、fileprivate
、internal
、public
、open
private
:只能在當前類class中訪問、extension修飾的拓展類中能夠訪問,可是子類及其餘類不可訪問fileprivate
:只能在當前源文件中訪問。也就是說不一樣文件中的子類也沒法訪問internal
:默認的訪問級別。在源代碼所在的整個模塊均可以被訪問public
:能夠被任何人訪問,在本模塊中能夠被override(重寫)和繼承,但在其餘的模塊中不能夠被override和繼承open
:能夠被任何人使用,包含override和繼承