由王巍 (@onevcat)發布於 2015/10/07
延時載入或者說延時初始化是很常用的優化方法,在構建和生成新的物件的時候,記憶體分配會在執行時耗費不少時間,如果有一些物件的屬性和內容非常複雜的話,這個時間更是不可忽略。另外,有些情況下我們並不會立即用到乙個物件的所有屬性,而預設情況下初始化時,那些在特定環境下不被使用的儲存屬性,也一樣要被初始化和賦值,也是一種浪費。
在其他語言 (包括 objective-c) 中延時載入的情況是很常見的。我們在第一次訪問某個屬性時,判斷這個屬性背後的儲存是否已經存在,如果存在則直接返回,如果不存在則說明是首次訪問,那麼就進行初始化並儲存後再返回。這樣我們可以把這個屬性的初始化時刻推遲,與包含它的物件的初始化時刻分開,以達到提公升效能的目的。以 objective-c 舉個例子 (雖然這裡既沒有費時操作,也不會因為使用延時載入而造成什麼效能影響,但是作為乙個最簡單的例子,可以很好地說明問題):
// classa.h
@property (nonatomic, copy) nsstring *teststring;
// classa.m
- (nsstring *)teststring
return _teststring;
}
在初始化classa
物件後,_teststring
是nil
。只有當首次訪問teststring
屬性時 getter 方法會被呼叫,並檢查如果還沒有初始化的話,就進行賦值。為了方便確認,我們還在賦值時列印了一句 log。我們之後再多次訪問這個屬性的話,因為_teststring
已經有值,因此將直接返回。
在 swift 中我們使用在變數屬性前加lazy
關鍵字的方式來簡單地指定延時載入。比如上面的的**我們在 swift 中重寫的話,會是這樣:
class classa ()
}
我們在使用lazy
作為屬性修飾符時,只能宣告屬性是變數。另外我們需要顯式地指定屬性型別,並使用乙個可以對這個屬性進行賦值的語句來在首次訪問屬性時執行。如果我們多次訪問這個例項的str
屬性的話,可以看到只有一次輸出。
為了簡化,我們如果不需要做什麼額外工作的話,也可以對這個lazy
的屬性直接寫賦值語句:
lazy var str: string = "hello"
相比起在 objective-c 中的實現方法,現在的 lazy 使用起來要方便得多。
另外乙個不太引起注意的是,在 swift 的標準庫中,我們還有一組lazy
方法,它們的定義是這樣的:
func lazy(s: s) -> lazysequence
func lazy(s: s)
-> lazyrandomaccesscollection
func lazy(s: s)
-> lazybidirectionalcollection
func lazy(s: s)
-> lazyforwardcollection
這些方法可以配合像map
或是filter
這類接受閉包並進行執行的方法一起,讓整個行為變成延時進行的。在某些情況下這麼做也對效能會有不小的幫助。例如,直接使用map
時:
let data = 1...3
let result = data.map
print("準備訪問結果")
for i in result
print("操作完畢")
這麼做的輸出為:
// 正在處理 1
// 正在處理 2
// 正在處理 3
// 準備訪問結果
// 操作後結果為 2
// 操作後結果為 4
// 操作後結果為 6
// 操作完畢
而如果我們先進行一次lazy
操作的話,我們就能得到延時執行版本的容器:
let data = 1...3
let result = data.lazy.map
print("準備訪問結果")
for i in result
print("操作完畢")
此時的執行結果:
// 準備訪問結果
// 正在處理 1
// 操作後結果為 2
// 正在處理 2
// 操作後結果為 4
// 正在處理 3
// 操作後結果為 6
// 操作完畢
對於那些不需要完全執行,可能提前退出的情況,使用lazy
來進行效能優化效果會非常有效。
from:
Swift lazy 修飾符和lazy 方法
延時載入或者說延時初始化是很常用的優化方法,在構建和生成新的物件的時候,記憶體分配會在執行時耗費不少時間,如果有一些物件的屬性和內容非常複雜的話,這個時間更不可忽略。另外,有些情況下我們並不會立即用到乙個物件的所有屬性,而預設情況下初始化時,那些在特定環境下不被使用的儲存屬性,也一樣要被初始化和賦值...
C 修飾符 類修飾符和成員修飾符
c 修飾符之類修飾符 public internal partial abstract sealed static internal 本程式集內的成員可以訪問。partial 部分類,可以將乙個類分成幾部分寫在不同檔案中,最終編譯時將合併成乙個檔案,且各個部分不能分散在不同程式集中。c 修飾符之成員...
java 類修飾符 成員變數修飾符 方法修飾符總結
類修飾符 public 訪問控制符 將乙個類宣告為公共類,他可以被任何物件訪問,乙個程式的主類必須是公共類。abstract,將乙個類宣告為抽象類,沒有實現的方法,需要子類提供方法實現。final,將乙個類生命為最終 即非繼承類 表示他不能被其他類繼承。friendly,預設的修飾符,只有在相同包中...