2017-03-01 162 views

回答

1

從蘋果文檔:

懶惰存儲屬性是一個屬性,其初始值是不計算使用它的第一次直到。通過在聲明之前編寫lazy修飾符來指示惰性存儲屬性。

使用時@lazy財產然後記住以下事情:

  • 懶惰的屬性必須始終與var關鍵字聲明,不與let不變。
  • 惰性屬性在聲明時必須初始化。

我們如何在Objective-C

@property (nonatomic, strong) NSMutableArray *players; 

- (NSMutableArray *)players 
{ 
    if (!_players) { 
     _players = [[NSMutableArray alloc] init]; 
    } 
    return _players; 
} 

實現懶的功能現在在斯威夫特,您可以通過使用lazy屬性實現同樣的功能。見下面的例子

class Person { 

    var name: String 

    lazy var personalizedGreeting: String = { 

     return "Hello, \(self.name)!" 
    }() 

    init(name: String) { 
     self.name = name 
    } 
} 

現在,當你初始化一個人,他們的個人問候語尚未創建:

let person = Person(name: "John Doe") // person.personalizedGreeting is nil 

但是當你試圖打印出個性化的問候語,它是計算上的-fly:

print(person.personalizedGreeting) 
// personalizedGreeting is calculated when used 
// and now contains the value "Hello, John Doe!" 

我希望這能幫助你理解懶惰屬性的功能。

+0

這與'NSMutableDictionary.lazy'無關。 – Alexander

0

懶惰的工作方式是初始化程序(或init方法)只在第一次訪問變量或屬性時才運行。我看到了一個主要原因,爲什麼它在你的代碼中不起作用(至少是直接),那是因爲你將兩個懶惰的實例化代碼打包到了一個方法中(loadEntriesIfNeeded)。

要使用惰性實例化,您可能需要擴展NSMutableArray和NSDictionary,併爲您的惰性實例化重寫或創建自定義初始化程序。然後,將loadEntriesIfNeeded中的代碼分發到它們各自的初始值設定項中。

import Swift 

println("begin") 

class ClassWithLazyProperties { 

    lazy var entries:[String] = ClassWithLazyProperties.loadStuff() 
    lazy var entriesByNumber:Dictionary<Int, String> = { 

     var d = Dictionary<Int, String>() 
     for i in 0..<self.entries.count { 
      d[i] = self.entries[i] 
     } 
     return d 
    }() 

    private class func loadStuff() -> [String] { 
     return ["Acai", "Apples", "Apricots", "Avocado", "Ackee", "Bananas", "Bilberries"] 
    } 

} 

let c = ClassWithLazyProperties() 
c.entriesByNumber 
    // 0: "Acai", 1: "Apples", 2: "Apricots", 3: "Avocado", 4: "Ackee", 5: "Bananas", 6: "Bilberries"] 


println("end") 
+0

這個問題與'lazy var's無關。另外,你應該避免在'self.entries.indices'中寫''in 0 .. Alexander

1

惰性求是當表達式的評估被延遲,直到所需要的結果。這與渴望評估形成對比,這是對錶達式的評估立即完成的時候。

考慮以下表達式:

let input = [1, 2, 3] 
let evens = input.map{ $0 * 2 } 

號碼的每個數字(1,2,3)由閉合{ $0 * 2 },其通過2.該評價急切地完成它們相乘映射到一個新的值。也就是說,執行該行的時刻是執行map函數的評估,並且計算結果存儲在evens中。 input類型爲Array<Int>,結果evens也是Array<Int>類型。

現在考慮以下表達式:

let input = [1, 2, 3] 
let evens = input.lazy.map{ $0 * 2 } 

號碼的每個數字(1,2,3)將由閉合{ $0 * 2 },其通過2.它們相乘然而是爲一個新值,該評價是懶惰地完成的。也就是說,在這一行正在執行的時候,乘法沒有完成。相反,關閉{ $0 * 2 }存儲供將來參考。 input類型爲Array<Int>,結果evens也是LazyMapRandomAccessCollection<Array<Int>, Int>類型。乘法推遲到元素爲訪問。如果一個元素永遠不會被訪問,那麼它就不會被處理。

在這樣一個微不足道的情況下,存儲閉包用於未來評估的簿記開銷將大於只是急切地計算結果。但是,你可以設想這樣的情況:

let input = 1...1000000000 
let evens = input.lazy.map{ $0 * 2 } 
print(evens[0]) 

所有序列中的1000000000中,只有一個被使用過。評估關閉1000000000次,以產生1000000000結果,如果只有第一個元素將被需要,將它們全部存儲在內存中實際上是低效的。

lazySequence協議的實例方法。所有符合的類型,包括NSMutableDictionary都執行它。它們都做同樣的事情:它們推遲處理mapfilter語句中的元素,直到需要結果爲止。這可以節省內存和處理時間,在有很多元素的情況下,只需要其中的一小部分。