1. 程式人生 > >Swift 學習之二十一:?和 !(詳解)

Swift 學習之二十一:?和 !(詳解)

新更新的內容請移步閱讀:

Swift語言使用var定義變數,但和別的語言不同,Swift裡不會自動給變數賦初始值,

也就是說變數不會有預設值,所以要求使用變數之前必須要對其初始化

。如果在使用變數之前不進行初始化就會報錯:

var stringValue : String 
//error: variable 'stringValue' used before being initialized
//let hashValue = stringValue.hashValue
//                            ^
let hashValue = stringValue.hashValue

出錯的原因就是在使用stringValue這個變數之前,沒有初始化這個變數,也就是這個變數根本就沒有得到記憶體,

這時就會出錯。

那麼我們可以使用optional型別,後面跟一個?就是了。

// 這就是optional, strValue自動得到預設值:nil 
// 這個nil跟Objective-C中的nil不同,不是指標,而是表示值不存在。
var strValue: String? 

// 判斷optional是否有值
if strValue {
 // do what you need to do here
}
文件中有提到說,在使用Optional值的時候需要在具體的操作,比如呼叫方法、屬性、下標索引等前面需要加上一個
,如果是nil值(不存在值),也就是Optional.None,會跳過後面的操作不執行,如果有值,就是Optional.Some可能就會拆包(unwrap),然後對拆包後的值執行後面的操作,來保證執行這個操作的安全性,比如Optional binding:
// optional binding
// 如果strValue == nil, 那麼結果就是nil,不會呼叫String的hasValue
// 如果strValue != nil, 就返回strValue對應的hashValue值並賦值給常量hashValue
if let hashValue = strValue?.hashValue {
  // do something if neccessary
}

在寫協議(protocol)時,對於可選代理方法,也需要在呼叫時在函式名後跟著?,如:
// @objc 是用於處理Swift與OC之間的轉換的,由於@optional是OC中的關鍵字,
// 所以在protocol之前需要新增上@objc。
@objc protocol HttpRequestDelegate {
  // @optional 說明這個代理方法是可選方法,
  // 那麼在呼叫的時候,需要這樣呼叫:delegate?.requestFinished?(self, downloadData)
  // 其中delegate?是因為delegate也是optional的
  @optional func requestFinished(request: HttpRequest!, downloadData: NSMutableData!)
  
  // other funcs ...
}

var delegate: HttpRequestDelegate?
var downloadData = NSMutableData()
delegate.requestFinished(self, downloadData)

當然我們也可以使用!來強制拆包,這是我們在保證有值的情況下才會這麼用:

var strValue: String?
strValue = "1234"

let integer = strValue!.toInt()
// 更安全的寫法是
if strValue {
  let integer = strValue!.toInt()
}

隱式強拆包型別:

使用!來宣告變數,會成為隱式強拆包可選型別,這表示這個型別永遠不會出現nil的情況,但一旦出來,

在呼叫時就會崩潰。

// Implicitly Unwrapped Optionals
// 使用這種方式宣告的話,在呼叫時不需要使用?或!來說明。
var myLabel: UILabel! 

myLabel = UILabel(frame: CGRectMake(10, 100, 300, 10))
myLabel.text = "label"


總結:

通常在什麼情況下才會使用optional型別呢?

(1)當我們需要宣告這樣一個變數,變數在設計初始化函式中沒有進行初始化時,就需要宣告這個變數為optional型別。因為變數在使用前必須先

        宣告,並且在設計初始化函式中進行初始化。比如我們在viewDidLoad函式中才進行初始化的控制元件(類成員),就需要宣告為optional且必須是var宣告,

       因為let宣告的常量只能是在初始化函式中進行初始化。

(2)當我們不知道是否會有值的時候,這個變數可以宣告為optional,比如代理,我們並沒有要求必須傳代理過來,那麼就需要宣告為optional。

(3)作為函式引數時,如果這個引數可以沒有值,那麼就使用optional型別,比如傳代理的時候,通常就是可選的,可以設定為nil

......暫時只想到這些,任何人都可以繼續往下補充!