有没有“计算”价值的成语?

时间:2016-03-09 23:24:36

标签: swift

请原谅我糟糕的头衔。如果有更好的事情,请更新它。

测试: 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

示例项目: https://github.com/qnoid/compute

2 个答案:

答案 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的答案感到满意,其余的仍然存在。但是,担心我可能会被未来的编译器优化所困扰。