Swift之延遲計算屬性

最近在寫Swift程序的時候,有個問題讓人難以理解,如下,上代碼,哥本就是這么一個直接的人,沒有什么能阻擋偶滴步伐。

lazy var tableView:UITableView = {

let tableView = UITableView()

tableView.frame = self.view.frame

tableView.dataSource = self

return tableView

}()

最后面那個()總是讓人覺得很尷尬,為啥非要加個()在后面呢?

首先,延遲計算屬性本質(zhì)上就是一個閉包,如果調(diào)用的時候這個屬性有值則直接使用,如果沒有值則觸發(fā)閉包的調(diào)用

舉個栗子,創(chuàng)建一個簡單的閉包

let myClosure = {()->String in

return "testString"

}

注意:閉包的靈活之處在于可以根據(jù)上下文推斷出自身的類型,大家不妨把()->String in 這段代碼刪掉,其實效果是一樣的。這很重要,官方有句話大致這個意思“事實上你可能不必寫出任何一個完整格式的閉包表達(dá)式”,說的就是閉包的靈活性問題

我們再聲明一個類,這個類里有一條屬性是一個閉包類型,當(dāng)然我一定會設(shè)計成()->String類型的,不然上面的閉包就沒有用處了

class Student {

var words:()->String

init(words:()->String) {

self.words = words

}

func say() {

// 這里如果我希望把學(xué)生的words打印出來,就需要調(diào)用閉包,調(diào)用閉包一定要使用括號,因為別忘了,閉包本質(zhì)就是匿名函數(shù)。

print("學(xué)生的話:\(self.words())")

}

}

現(xiàn)在創(chuàng)建一個Student實例,把myClosure作為參數(shù),再調(diào)用他的say函數(shù)

let xiaoMing = Student(words: myClosure)

xiaoMing.say()

打印結(jié)果如下

學(xué)生的話:testString

現(xiàn)在我把上面的例子稍作修改,我們使用一個字符串類型的屬性去記錄學(xué)生要說的話,而學(xué)生的話仍然有這個閉包獲取,那么上面的程序變成下面的樣子

class Student {

var words:()->String

init(words:()->String) {

self.words = words

}

// 因為閉包獲取的值編譯器無法確定獲取時間,所以不能再實例初始化一開始就賦值,所以這個message屬性必須使用lazy來聲明,并且它必須是var類型,因為它必須是可寫入的

// lazy var message:String = self.words()

// 如果上面這行代碼可以如上那樣寫,那么一定也可以如下這樣寫

lazy var message:String = {()->String in

return "closureString"

}()

func say() {

// 這里我們就可以把之前的閉包調(diào)用,改成屬性的調(diào)用了

print("學(xué)生的話:\(self.message)")

}

}

我們在實例化學(xué)生對象來觀察結(jié)果

let xiaoHong = Student(words: myClosure)

xiaoHong.say()

打印結(jié)果如下

學(xué)生的話:closureString

所以這個時候,我們想實現(xiàn)最開始的功能,可以把程序修改成如下的樣子

class Student {

func say() {

print("學(xué)生的話:\(self.message)")

}

//? ? lazy var message:String = {()->String in

//? ? ? ? return "closureString"

//? ? }()

// 由于閉包可以自動推斷自身的類型,所以可以省略成這個樣子

lazy var message:String = {

return "closureString"

}()

}

最終我們的程序變成下面的樣子了

class Student {

func say() {

print("學(xué)生的話:\(self.message)")

}

lazy var message:String = {

return "closureString"

}()

}

是不是很簡潔?所以在使用延遲計算屬性的時候,不要忘記后面的小括號哦!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容