Swift - 懶加載(lazy initialization)

Swift中是存在和OC同樣的懶加載機制的,在程序設計中,咱們常常會使用 懶加載 ,顧名思義,就是用到的時候再開闢空間javascript

 

懶加載

  • 格式:
lazy var 變量: 類型 = { 建立變量代碼 }()
  • 懶加載的寫法本質上是定義並執行一個閉包
// 含義: 當dataList被使用到時, 就會執行等號後面的閉包 // 因此等號後面的閉包的()是必須寫的, 若是不寫就會報錯 // 注意點: 若是寫懶加載, 那麼修飾符必須用var lazy var dataList:[String] = { print("我被加載了") return ["lnj", "lmj", "zs"] }()
lazy var satatuses: [String] = self.loadStatus() func loadStatus() -> [String] { print("我被加載了") return ["lnj", "lmj", "zs"] }


// 懶加載java

 
   

    private lazy var inputeTextField: UITextField = {swift

 
   

        let inputeTextField = UITextField()安全

 
   

        inputeTextField.keyboardType = .NumberPad閉包

 
   

        /*app

 
   

         8種鍵盤風格:函數

 
   

        UIKeyboardTypeDefault,                // 默認鍵盤:支持全部字符優化

 
   

        UIKeyboardTypeASCIICapable,           // 支持ASCII的默認鍵盤ui

 
   

        UIKeyboardTypeNumbersAndPunctuation,  // 標準電話鍵盤,支持+*#等符號atom

 
   

        UIKeyboardTypeURL,                    // URL鍵盤,有.com按鈕;只支持URL字符

 
   

        UIKeyboardTypeNumberPad,              //數字鍵盤

 
   

        UIKeyboardTypePhonePad,               // 電話鍵盤

 
   

        UIKeyboardTypeNamePhonePad,           // 電話鍵盤,也支持輸入人名字

 
   

        UIKeyboardTypeEmailAddress,           // 用於輸入電子郵件地址的鍵盤

 
   

        */

 
   

        inputeTextField.delegate = self

 
   

        inputeTextField.hidden = true

 
   

        return inputeTextField

 
   

    }()

 
 


咱們在OC中通常是這樣實現懶加載初始化的:

   1: @property (nonatomic, strong) NSMutableArray *players;

   2:   
   3:  - (NSMutableArray *)players {
   4:      if (!_players) {
   5:          _players = [[NSMutableArray alloc] init];
   6:      }
   7:      return _players;
   8:  }

 

實際上咱們能夠這樣寫:

   1:  lazy var players: NSMutableArray = {
   2:          var temporaryPlayers = NSMutableArray()
   3:          temporaryPlayers.addObject("Mike Buss")
   4:          return temporaryPlayers
   5:          }()

 

好比iOS開發中的最經常使用控件UITableView,實現數據源方法的時候,一般咱們都會這樣寫

Objective-C

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.dataArray.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ //1.獲得cell XWShopCell *cell = [XWShopCell cellWithTableView:tableView]; //2.傳遞模型 cell.wine = self.dataArray[indexPath.row]; //3.回傳cell return cell; }

上面的的代碼中

return self.dataArray.count;

其實就是利用

@property (nonatomic, strong) NSArray *dataArray;

@property 的特性,爲屬性生成了getset方法,而這裏是調用的get方法,可是上述代碼中return self.dataArray.count 會調用

- (NSArray *)dataArray{ return _dataArray}

這樣調用,若是成員屬性dataArray 開始沒有賦值的,那麼在使用的時候,調用get方法,不重寫的話,會報錯,空指針,因此通常咱們會重寫get方法

//重寫get方法 - (NSArray *)dataArray { if (nil == _dataArray){ _dataArray = [NSArray array]; } return _dataArray }

這樣寫,就防止了成員屬性爲沒有賦值的狀況

綜上所述,Objective-C的懶加載,其實就是調用成員屬性的get方法,初始化值,而Swift的懶加載,是和Objective-C不一樣的


Swift

//MARK tablview的 dataSource 代理方法 func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{ return self.dataArray.count } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{ //1.獲得cell let cell = XWShopCell.cellWithTableView(tableView) //2.傳遞模型 cell.wine = self.dataArray[indexPath.row] //3.回傳cell return cell }

而這句

return self.dataArray.count

Swift 存儲屬性必須初始化,確認類型,或者用可選類型,總之要確認類型,畢竟Swfit是類型安全語言,因此Swift提出了lazy屬性,用法

//1.分析 NSArray 是一個閉包的返回值,而這是一個沒有參數的閉包 lazy var dataArray:NSArray = { [] }() //2.也能夠寫成這樣 lazy var dataArray:NSArray = { return NSArray() }() //3.從plist文件加載 lazy var dataArray:Array<XWWine> = { let winePath = NSBundle.mainBundle().pathForResource("wine.plist", ofType: nil)! let winesM = NSMutableArray(contentsOfFile: winePath); var tmpArray:Array<XWWine>! = [] for tmpWineDict in winesM! { var wine:XWWine = XWWine.wineWithDict(tmpWineDict as! NSDictionary) tmpArray.append(wine) } print("我就運行一次") return tmpArray }()

上述的代碼,有點難理解,若是以前會Objective-Cblock 或者對C語言的函數指針理解透徹的,能夠當作是一個代碼塊,而後self.dataArray的時候,就執行了代碼塊,可是重複調用,Lazy 屬性的代碼塊只會調用一次,lazy修飾的是一個存儲屬性,而存放的是閉包,我想內部,應該進行了優化

 

Swift 懶加載小議

lazy var zyTableView: UITableView = { let tempTableView = UITableView (frame: self.view.bounds, style: UITableViewStyle.Plain) tempTableView.delegate = self tempTableView.dataSource = self return tempTableView }() 這是Swift中懶加載一個叫作zyTableView的變量。 咱們今天就主要來講說這段代碼.

先來講一下懶加載的好處:

  • 須要的時候初始化內存,對內存開銷較小,節省內部資源
  • 代碼初始化放在一塊兒,代碼塊比較好劃分,方便別人和本身閱讀

再來講一下有爭議的地方,我剛纔在幾個羣裏問懶加載效率低不低,有不一樣意見,有人說低,也有人說不低,我以爲懶加載效率是低的,最簡單的說法:

在你須要使用肥皂的時候,你沒有肥皂,而後去撿一個肥皂,和你須要使用肥皂的時候就有肥皂了,你以爲哪一個效率高?懶加載就是現去撿肥皂呀,因此,懶夾在效率低。

再來看看Swift中懶加載的本質,引用絕影的原話:

它本質在siwft中確實是一個閉包,執行順序是這樣的,若是這個lazy修飾的變量沒值,就會執行閉包中的東西,不是每次都執行(本人補充:這也就是爲何在Swift中的懶加載沒有oc中判斷。if(xx==nil){初始化xx}的代碼段)。

在來看下一個問題,既然懶加載在Swift中是一個閉包,那麼就用閉包來複寫一個懶夾在咯:

let name = { () -> String in return "..." } lazy var myName:String = self.name()

最後呢,若是懶夾在初始化失敗怎麼辦?
答案:可選值。

lazy var value1:String = { return "aaa" }() lazy var value2:String? = { return nil }() lazy var value1:String 等價於 lazy var value1:String!
相關文章
相關標籤/搜索