
可選變量:
一. 在Swift中可選類型(Optionals),用 " ? " 號表示, 用于處理值缺失的情況. 表示"該處有一個值, 切它等于X", 或者表示"該處沒有值"
二. 可選類型是一個包含兩種情況的枚舉值: None 和 Some , 用來表示可能有值(Some) 或可能沒有值(None)
2.1 nil 就是Optional.None, 當你聲明一個可選變量, 或者可選屬性的時候, 沒有提供初始化值, 它的值默認為 nil
2.2 非nil 就是Optional.Some
三. 任何類型都可以明確的聲明為可選類型, 當聲明一個可選類型的時候, 要確保用括號給" ? " 操作符一個合適的范圍. 例如: 聲明可選整數數組, 格式為: (Int[])?, 如果寫成"Int[]?", 就會報錯
定義一個可選類型: 兩種方式
var Optional_1:Int? //注意: 在數據類型和" ? "號之間沒有空格
var Optional_2:Optional<Int> // 這里表明關鍵字可選類型
四: " ! " 號, 用來表示強制解析, 如果可選類型實例包含一個值, 可以用" ! "號來訪問這個值.
注意: 如果可選類型在沒有賦值的情況下, 進行強制解析, 會導致崩潰
var intNumber:Int? = 8
var result1 = intNumber // 打印結果Optional(8)
var result2 = intNumber! // 打印結果直接是 8
print(result1, result2
五. 自動解析(隱式解析)
5.1 你可以在聲明可選變量時, 使用 " ! " 號來替換 " ? ", 這樣可選變量在使用時, 就不需要在加一個 " ! "進行解析了, 它會自動解析.
5.2 隱式解析可選類型和可選類型一樣, 都是有值和沒有值(nil)兩種結果.
5.3 區(qū)別在于賦值/取值時, 隱式解析可選類型不需要再強制解析
5.4 注意: 隱式解析可選類型的變量沒有值時, 程序一樣會崩潰
var IntNumberOne:Int! = 10
print(IntNumberOne)
六. 可選綁定
6.1 可選綁定: 用來判斷, 可選類型是否包含值, 如果包含就把值賦給一個臨時常量/臨時變量
6.2:可選綁定可以用在 if 和 while 語句中來對可選類型的值進行判斷, 并把他賦給一個常量或者變量
6.3 如果你不確定類型是否有值, 用可選綁定, 不需要對可選類型強制解析
var intNumberTow:Int?
if var intNumberThree = intNumberTow
{
print("可選類型有值 = ",intNumberThree)
}else
{
print("可選類型沒有值")
}```
--------------------
結構體:
-------
>一: 與 C 和 OC 不同的是:
1.1: 結構體不需要包含實現文件和接口文件
1.2: 結構體允許我們創(chuàng)建一個單一文件, 且系統(tǒng)會自動生成該結構體面向其他代碼的外部接口
> 二: 結構體總是通過被復制的方式在代碼中傳遞, 因此, 該結構體原本的值是不可修改的
>三: 結構體的應用
3.1: 在代碼中可以使用結構體定義你的自定義類型數據
3.2: 按照通用的準則, 當符合一條或者多條以下條件時候, 請考慮構建結構體
>> 3.2.1: 結構體的主要目的是用來封裝少量相關簡單數據
3.2.2: 有足夠的理由預計一個結構體實例在賦值或者傳遞時, 封裝的數據將會被拷貝而不是應用
3.2.3: 任何結構體中存儲的值類型屬性, 也將會被拷貝, 而不是被應用
3.2.4: 結構體不需要繼承另一個已經存在類型的屬性或者行為
> 四: 舉例:
4.1: 幾何形狀大小, 封裝一個 width 屬性和 height 屬性,兩者均為 Double 類型
4.2: 一定范圍的路徑, 封裝一個 Start 屬性和 Length 屬性, 兩者均為 Int 類型
4.3: 三維坐標系內的一點, X, Y, Z, 三者均為 Double 類型
``` code
// 聲明一個結構體
struct piontOf3D
{
// 聲明結構體變量的屬性 (存儲屬性)
var X : Double
var Y : Double
var Z : Double
}
// 創(chuàng)建結構體實例
var D3:piontOf3D = piontOf3D.init(X: 1, Y: 1, Z: 1)
// 聲明一個結構體
struct Rect
{
var ponit : (x : Int , y : Int) = (0 , 0)
var size :(w :Int , h : Int ) = (0 , 0)
// 成員方法
func getSize()
{
print(size)
}
// 類方法 : 用 Static 修飾
static func sayHellon ()
{
print("你好, 我是結構體類方法")
}
}
var rect2 : Rect = Rect.init(ponit: (x: 10, y: 10), size: (w: 20, h: 20))
// 調用成員方法
rect2.getSize()
// 調用類方法 (用結構體名調用)
Rect.sayHellon()
類:
一 : swift 中類和結構體有很多共同點
1.1: 定義屬性, 用于存儲值
1.2: 定義方法, 用于提供功能
1.3: 定義構造器, 用于提供初始化值
1.4: 遵循協議, 用來對某個類提供標準功能
1.5: 通過擴展, 用來增加默認實現的功能
二 : 與結構體 相比又有其他附加功能
2.1: 繼承允許一個類繼承另一個類的特征
2.2: 類型轉換允許在運行時檢查和解釋一個類實例的類型
2.3: 引用計數: 允許對一個類多次引用
三 : 存儲屬性: 存儲屬性就是類或者結構體里定義的變量 (或者變量) (OC 中的一個類中引用另一個類)
3.1: 存儲屬性可以是變量存儲屬性(var 修飾), 也可以是常量存儲屬性(let 修飾)
3.2: 可以在定義存儲屬性的時候指定默認值
3.3: 也可以在構造過程中設置或者修改存儲屬性的值
四: 計算屬性 不直接存儲值, 而是提供一個 getter 和一個可選的 setter, 來間接獲取和設置其他屬性常量或者變量的值
// 聲明一個類
class Car
{
// 聲明存儲屬性
var kind : String?
// 聲明計算屬性
var number : Int
{
get
{
return 10
}
set
{
print(newValue) // 相當于這個傳入參數
}
}
// 構造方法
init (kind : String)
{
self.kind = kind
}
}
// 創(chuàng)建實例對象
var volvo = Car (kind: "BMW")
// 訪問
print(volvo.kind,volvo.number)
// 聲明類屬性
class Docter
{
// 類屬性只能類方法調用
static var name : String?
// 聲明類方法 static 修飾 子類不可以重寫 類方法中只能使用類屬性 不能使用對象屬性
static func sayBybeBybe ()
{
print(name)
}
// 子類可以重寫的類方法
class func sayNoByble()
{
print(name)
}
// 對象方法
func sayGoodBybe()
{
print("我就是實例方法")
}
var age : Int?
var Number : Int{
get
{
return age!
}
set (value)// 這種寫法表示在調用的 Number的 set 方法時, 傳過來參數賦給 value
{
age = value // 切記: set\get 方法中不能使用"self.名稱 ", 會造成遞歸
}
}
// 構造方法中不能使用類屬性
}
var DaPeng : Docter = Docter()
DaPeng.sayGoodBybe()
// 繼承
class nurse: Docter
{
override class func sayNoByble()
{
print("重寫了父類的方法, 使用 override 修飾")
}
}
值類型與引用類型:
一:值類型:
該類型的每一個實例持有數據的副本, 并且該副本對于每一個實例來說都是唯一的一份, 比如結構體, 枚舉, 元組都是值類類型
二: 值類型使用場景
2.1: 當使用"==" 運算符比較實例數據的時候
2.2: 當想單獨賦值一份實例數據的時候
2.3: 在多線程環(huán)境下操作數據的時候
三: 引用類型(如同 OC 中的指針指向同一內存)
該類型的實例共享數據唯一的一份副本, 比如說(class)類就是引用類型
值類型:
struct StructObject
{
var data : Int = 1
}
var value_1 : StructObject = StructObject()
// 將 value_1 的值賦給 value2, 就是一個拷貝的過程
var value_2 = value_1
print(value_2)
// 這里只能改變 value_1 的值 不能改變 value_2 的值 這些都是值類型
value_1.data = 0
print("值引用都是副本\(value_1.data)************\(value_2.data)")
引用類型:
class ClassObjecct
{
var data : Int = -1
}
var cob_1 = ClassObjecct()
// 將 cob_1的值賦給 cob_2, 就是引用的過程
var cob_2 = cob_1
cob_1.data = 4
print("引用類型, 改一個全部改了",cob_1.data, cob_2.data)
var cob_3 = ClassObjecct()
print(cob_3.data)
協議:
- 1: 協議定義了一個藍圖,規(guī)定了用來實現某一特定工作或者功能所必需的方法和屬性
- 2: 類, 結構體, 枚舉都可以遵守協議, 并提供具體實現來完成協議定義的方法和功能
- 3: 任意能夠滿足協議要求的類型, 被稱為(conform)這個協議
- 4: 使用"@objc"修飾的協議, 其中的方法, 可以聲明成可選實現(用 optional 修飾)
注意1:
- 使用@objc修飾的協議表示 OC 的協議
- @objc修飾的協議
不可用在結構體里面遵守 - 使用@objc修飾的協議里可以聲明可選實現的函數(用
optional修飾函數) - 在實現這個函數的時候,在函數前面要加
@objc修飾
注意2:
- 使用
mutating修飾的函數可以在結構體里面修改結構體的屬性 - 協議里面使用mutating修飾的函數,在遵守協議的時候可以不使用mutating修飾,在類里沒有影響,在結構體力面,就不能修改屬性的值了.
- 但是如果實現協議里沒有mutating修飾的函數的時候,卻用了mutating修飾,結果是在結構體重新聲明了一個函數,此函數和協議無關系
// 帶有可選實現函數的協議
@objc protocol MenDelegate
{
func cook()
func wash()
optional func hitJJ()
}
// 必須實現的 函數協議
protocol DividDelegate
{
func lookKid()
}```
- 要遵循某個協議, 如果類在遵循協議的同時擁有父類, 應該將父類名放在協議之前, 用逗號隔開
```code
# doc 繼承于 Docter類 遵守 MenDelegate,DividDelegate協議
class doc: Docter,MenDelegate,DividDelegate
{
#實現協議方法
@objc func cook() {
print("做飯的女人")
}
@objc func wash() {
print("洗衣服的女人")
}
func lookKid() {
print("照顧孩子")
}
}
// 創(chuàng)建實例 并調用類的實例方法
var doc1 : doc = doc()
doc1.cook()
doc1.lookKid()
doc1.wash()
延展:
1: Extension + 類名或者結構體名 (可以給一個類或者結構體擴展方法)
2: Extension 可以多次對一個類進行擴展, 也可以給一個類擴展協議方法
3: 擴展就是向一個已有的類, 結構體, 枚舉添加新功能
4: 擴展可以對一個類型添加新的功能, 但是不能重寫已有的方法
// 給 doc 類擴展方法
extension doc
{
// 實例方法
func say()
{
print("i-LOVE-u")
}
// 擴展類方法
class func eat()
{
print("i-WANT-u")
}
}
doc.eat()
doc1.say()
// 擴展一個 類 遵循協議中的方法
@objc protocol Magic
{
func magic ()
}
extension doc : Magic
{
@objc func magic()
{
print("我會變魔術")
}
}
var docc : doc = doc()
docc.magic()
// 給協議新添加方法并實現 遵循這個協議的實例可以調用這個方法
// 擴展一個 類遵循協議 中的方法
extension MenDelegate
{
func magic()
{
print("12345678")
}
}
class stu : MenDelegate
{
@objc func wash() {
}
@objc func cook() {
}
}
var sutt : stu = stu()
sutt.magic()
閉包:
1: 閉包: 是自包含的函數代碼塊, 可以再代碼中被傳遞, 使用
2: Swift 中的閉包和 OC 中的 Block 以及其他語言中的匿名函數類似
3: 閉包可以捕獲和存儲其所在上下文中任意的常量和變量 (閉包并包裹著這些常量和變量)
4: Swift 會幫你管理在捕獲過程中涉及到的內存操作
5: 格式: {(參數名 : 類型) ->返回值類型 in 需要執(zhí)行的代碼 }
6: let backString = {(name : String) -> String in return name }
7: 閉包的函數體部分由關鍵字 in 引入, 該關鍵字表示閉包的參數和返回值類型定義已經完成, 閉包函數體即將開始
代碼舉例:
// 求兩個數的最大值
// (a : Int , b : Int ) -> Int是表示maxReult的函數類型
var maxReult : ((a : Int , b : Int ) -> Int )
// 第一種方式
maxReult = {(a : Int , b : Int ) -> Int in
return a > b ? a : b
}
// 第二種方式
maxReult = { a , b -> Int in return a > b ? a : b }
// 第三種方式
maxReult = { a , b in a > b ? a : b }
// 第四種方式 (官方推薦)
maxReult = {( a , b) -> Int in return a > b ? a : b }
// 第五種方式
maxReult = { $0 > $1 ? $0 : $1 }
print(maxReult(a: 3,b: 5))