请原谅我糟糕的头衔。如果有更好的事情,请更新它。
测试: Xcode版本7.2.1(7C1002)
我希望利用Swift的惰性存储属性在从主队列访问属性之前在“后台”队列中计算属性的值。
这是一个定义惰性存储属性的类
class Cache {
lazy var heavilyComputational = {
return 42
}()
}
这是一个示例用法
dispatch_async(dispatch_queue_create("com.qnoid.compute", DISPATCH_QUEUE_CONCURRENT)){
let cache = Cache()
let _ = cache.heavilyComputational
dispatch_async(dispatch_get_main_queue()){
debugPrint(cache.heavilyComputational)
}
}
有效。
除了警告之外,IMO意图不明确。
一个懒惰的属性是懒惰计算的是,但在这种情况下,“where”,“when”和“why”同样重要且不那么清楚。
试图通过使用像这样的结构“聪明”来澄清意图
struct Compute {
var function: () -> Void {
didSet{
function()
}
}
}
dispatch_async(dispatch_queue_create("com.qnoid.compute", DISPATCH_QUEUE_CONCURRENT)){
let cache = Cache()
Compute {
cache.heavilyComputational
}
dispatch_async(dispatch_get_main_queue()){
debugPrint(cache.heavilyComputational)
}
}
但由于未使用Compute实例,编译器通过删除指令(AFAICT)来“智取”我。 FWIW,这是在Debug配置上,我只能在Release上假设它会更加激进。
为了进行比较,这可以按预期工作(*不是didSet调用)
dispatch_async(dispatch_queue_create("com.qnoid.compute", DISPATCH_QUEUE_CONCURRENT)){
let cache = Cache()
let compute = Compute {
cache.heavilyComputational
}
compute.function()
dispatch_async(dispatch_get_main_queue()){
debugPrint(cache.heavilyComputational)
}
}
但到那时,整个目的都被打败了。
1。我误解了什么吗?
2.是否有一个原生的构造允许在Swift中使用这样的东西?
3。如果没有,有没有办法重写这个代码,以便明确意图?
4.为什么不调用 didSet ?
答案 0 :(得分:3)
看来你有点意识到这个问题。据我所知,如果在init
方法中,didSet将无法触发。
在你的情况下,当你做
Compute {
cache.heavilyComputational
}
它实际上使用结构的init
方法设置function
属性,该属性不会触发didSet
。
在您的第二次尝试中,由于您明确调用function()
,然后调用cache.heavilyComputational
,因此您手动触发heavilyComputational
的延迟初始化。它几乎等同于您的原始(没有Compute
struct)方法。
要使你的结构在不调用函数的情况下工作,你必须做一些黑客攻击。
struct Compute {
var function: () -> Void = {} {
didSet{
function()
}
}
init(function: () -> Void) {
setFunction(function)
}
private mutating func setFunction(function: () -> Void) {
self.function = function
}
}
那么你就可以做到
Compute {
cache.heavilyComputational
}
为了进一步改进,我必须考虑一下。
答案 1 :(得分:0)
我相信我已经找到了一个简单的答案。
struct Compute {
init(f: () -> Void) {
f()
}
}
对问题3的答案感到满意,其余的仍然存在。但是,担心我可能会被未来的编译器优化所困扰。