如何在Swift中实现以下模式?
使用包含字典的JSON数组初始化Container
类。这些词典用于初始化Entry
类。但是,当访问Entry
或entries
属性时,searchEntries
对象的初始化会延迟发生。
@interface Container
@property (readonly, nonatomic) NSArray *entryDicts;
@property (readonly, nonatomic) NSArray* entries;
@property (readonly, nonatomic) NSDictionary *searchEntries;
@end
@implementation Container
- (instancetype)initWithArray:(NSArray *)array
{
self = [super init];
if (self) {
_entryDicts = array;
}
return self;
}
@synthesize entries = _entries;
- (NSArray *)entries
{
[self loadEntriesIfNeeded];
return _entries;
}
@synthesize entriesByNumber = _entriesByNumber;
- (NSDictionary *)entriesByNumber
{
[self loadEntriesIfNeeded];
return _entriesByNumber;
}
- (void)loadEntriesIfNeeded
{
if (_entries == nil) {
// Load entries
NSMutableArray *entries = [NSMutableArray arrayWithCapacity:[self.entriesDict count]];
NSMutableDictionary *entriesByNumber = [NSMutableDictionary dictionaryWithCapacity:[self.entriesDict count]];
[self.entriesDict enumerateKeysAndObjectsUsingBlock:^(NSString *number, NSDictionary *entryDict, BOOL *stop) {
Entry *entry = [[Entry alloc] initWithDictionary:entryDict container:self];
[entries addObject:entry];
entriesByNumber[number] = entry;
}];
_entries = [entries copy];
_entriesByNumber = [entriesByNumber copy];
// Delete dictionaries
_entriesDict = nil;
}
}
@end
答案 0 :(得分:9)
这个怎么样:
class Container {
lazy var entries: [String] = self.newEntries()
func newEntries() -> [String] {
// calculate and return entries
}
}
答案 1 :(得分:6)
似乎这个问题在很大程度上得到了回答,但回到原帖,这里(恕我直言)是一个相对简洁的Swift翻译。关键是你可以链接惰性属性。请注意,我使用了类函数和闭包 - 两者都没问题。
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")
答案 2 :(得分:5)
您可以使用optional作为实例变量。然后创建一个函数,如果它存在则返回可选项,如果不模拟延迟加载则创建一个新对象。
class Lazy {
var lazyVariable:String?
func lazilyGetEntries() -> String {
if let possibleVariable = self.lazyVariable { // optional already exists
return possibleVariable
}
else { // optional does not exist, create it
self.lazyVariable = String()
return self.lazyVariable!
}
}
}
答案 3 :(得分:3)
延迟工作的方式是初始化程序(或init方法)仅在首次访问变量或属性时运行。我看到它在代码中不能工作(至少是直接)的一个主要原因,那是因为你将两个惰性实例化代码打包到一个方法中(loadEntriesIfNeeded
)。
要使用延迟实例化,您可能需要扩展NSMutableArray和NSDictionary,并为您的延迟实例化覆盖或创建自定义初始化程序。然后,将loadEntriesIfNeeded
内的代码分发到各自的初始值设定项中。
在条目初始化程序中:
NSMutableArray *entries = [NSMutableArray arrayWithCapacity:[self.entriesDict count]];
[self.entriesDict enumerateKeysAndObjectsUsingBlock:^(NSString *number, NSDictionary *entryDict, BOOL *stop) {
Entry *entry = [[Entry alloc] initWithDictionary:entryDict container:self];
[entries addObject:entry];}];
_entries = [entries copy];
然后在entriesByNumber初始化程序中:
NSMutableDictionary *entriesByNumber = [NSMutableDictionary dictionaryWithCapacity:[self.entriesDict count]];
// Then do fast enumeration accessing self.entries to assign values to entriesByNumber.
// If self.entries is null, the lazy instantiation should kick in, calling the above code
// and populating the entries variable.
_entriesByNumber = [entriesByNumber copy];
然后,您可以通过调用自定义初始值设定项来创建惰性变量。
@lazy var entries: CustomArray = custominitforarray()
@lazy var entriesByNumber: CustomDictionary = custominitfordictionary()
PS:你怎么没有entryByNumber的财产?我猜它是私人的吗?请测试一下并回复结果,因为我自己太懒了。
答案 4 :(得分:2)
您可以在Swift中使用Lazy Stored Properties来实现Lazy Instantiation模式。这是通过在声明存储属性之前添加@lazy
属性来完成的。
要记住两件事:
这里有一些代码可以放入Playground以查看@lazy
属性的工作原理
// initialize your lazily instantiated data
func initLazyData() -> String[] {
return ["lazy data"]
}
// a class to manage the lazy data (along with any other data you want)
class DataManager {
@lazy var lazyData = initLazyData()
var otherData = "Other data"
}
// when we create this object, the "lazy data" array is not initialized
let manager = DataManager()
// even if we access another property, the "lazy data" array stays nil
manager.otherData += ", more data"
manager
// as soon as we access the "lazy data" array, it gets created
manager.lazyData
manager
有关详细信息,请查看“Swift编程语言指南”的“属性”页面上的Lazy Stored Properties部分。请注意,该链接是预发布文档。
答案 5 :(得分:0)
通过在声明之前编写@lazy属性来指示延迟存储的属性。“
@lazy var lazyVariable:String? = ""
请注意,懒惰的财产必须有初始化。
答案 6 :(得分:0)
Swift中有@lazy
个属性。我发现了一个小帖here,我建议观看来自Apple here的三个Swift视频(Swift简介,中级Swift,高级Swift)。这些视频显示了很多内容,而高级视频确实很先进......
答案 7 :(得分:0)
我在PageBaseApplication
中找到了这个var modelController: ModelController {
// Return the model controller object, creating it if necessary.
// In more complex implementations, the model controller may be passed to the view controller.
if !_modelController {
_modelController = ModelController()
}
return _modelController!
}
var _modelController: ModelController? = nil
类似于@Brian Tracy所提到的但是使用变量而不是func
答案 8 :(得分:0)
由于entries
属性只是entriesByNumber
中值的数组,因此您可以在entriesByNumber
中执行所有加载,只需entries
取决于{{1} }}
entriesByNumber