Swift:捕获逃脱被调用函数的闭包中的inout参数 [英] Swift: Capture inout parameter in closures that escape the called function

查看:95
本文介绍了Swift:捕获逃脱被调用函数的闭包中的inout参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试编写一个编辑器类,它可以保留对不同对象上的属性的引用,以便以后进行突变。我首先编写了编辑器类来接收一个用于读取的闭包,以及一个用于写入的闭包。这很有效。然后我尝试通过(inout)引用传递有问题的参数,然后从中生成getter / setter对。这没用。 Swift文档确实说(释义)Swift确定何时复制,何时不复制。我认为我反对这种限制的不可预测性,但我认为我提出的问题是一样的。

I tried to write an "editor" class that could retain a reference to a property on a different object for later mutation. I first wrote the editor class to receive a closure for reading, and a closure for writing. This worked. I then tried to pass the parameter in question by (inout) reference, and then generate the getter / setter pair from that. This did not work. The Swift docs does say (paraphrasing) that Swift figures out when to copy, and when to not. I think I am up against unpredictability of that limitation, but thought I'd pose the question just the same.

或者,是否可以获得个人getter和setter的curried函数?

Alternatively, is it possible to get a curried function for the individual getter and setter?

我的代码是:

class SomeModel : Printable {

    var a:String

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

    var description:String {
        return "\(self.a)"
    }
}


class Editor {

    var getter:()-> String
    var setter:(String)->()

    init(getter:()-> String, setter:(String)->()) {
        self.getter = getter
        self.setter = setter
    }

    convenience init(inout bindTo:String) {
        self.init(
            getter:{ return bindTo },
            setter: { v in bindTo = v })
    }

    func read() -> String {
        return self.getter()
    }

    func write(value:String) {
        self.setter(value)
    }
}


func testBindTo() {
    var readModel =  SomeModel(a:"Did not capture by reference");
    var bindForReading = Editor(bindTo: &readModel.a)
    readModel.a = "captured by reference!"
    println(bindForReading.read())

    var writeModel =  SomeModel(a:"Did not capture by reference");
    var bindForWriting = Editor(bindTo: &writeModel.a)
    bindForWriting.write("captured by reference")
    println(writeModel)
}

testBindTo()


func testExplicitGetterSetter() {

    var readModel =  SomeModel(a:"Did not capture by reference");
    var bindForReading = Editor(
        getter: { readModel.a },
        setter: { v in readModel.a = v })
    readModel.a = "captured by reference!"
    println(bindForReading.read())

    var writeModel =  SomeModel(a:"Did not capture by reference");
    var bindForWriting = Editor(
        getter: { writeModel.a },
        setter: { v in writeModel.a = v })
    bindForWriting.write("captured by reference")
    println(writeModel)     
}

testExplicitGetterSetter()

结果如下:

Did not capture by reference
Did not capture by reference
captured by reference!
captured by reference

谢谢!

推荐答案

我不认为这是可能的。并且不应该是可能的,如果你考虑它,因为它会超级不安全。

I don't think this is possible. And it shouldn't be possible, if you think about it, because it would be super unsafe.

因为闭包可以比他们的范围更长在创建时,捕获的变量必须与块一起存储。但是为了能够分配给捕获的变量并在捕获它的(一个或多个)块和原始范围之间共享该变量的状态,这些块不能只捕获变量的值(将创建变量的独立副本),但捕获一种对共享副本的引用。这意味着必须专门存储由块捕获的可分配变量。在Objective-C中,这是用 __ block 声明的。在Swift中,这个 __ block 行为是隐式的。

Because closures can outlive the scope they were created in, captured variables must be stored with the block. But in order to be able to assign to the captured variable and share the state of that variable between the (one or more) block(s) that captured it and the original scope, the blocks cannot just capture the value of the variable (which would create independent copies of the variable), but capture a kind of "reference" to a shared copy. This means that assignable variables that are captured by blocks must be stored specially. In Objective-C, this is declared with __block. In Swift, this __block behavior is implicit.

然而,为了让块修改 inout 变量(可能在稍后的时间),如在函数调用者的作用域中看到的那样,这意味着调用者作用域中传递的变量也需要以这样的方式存储:可以比堆栈帧寿命更长。但调用函数不知道这一点。根据被调用函数的类型,它所知道的是它的一个参数是 inout ;它不知道函数计划在块中捕获 inout 变量。所以它不知道为这个传递的变量准备这个 __ block 存储。

However, in order for the block to modify an inout variable (potentially at a later time) as it is seen in the function caller's scope, that would mean that the passed variable in the caller's scope would also need to be stored in a way that can outlive the stack frame. But the caller function doesn't know this. All it knows from the type of the called function is that one of its parameters is inout; it doesn't know that the function plans to capture that inout variable in a block. So it doesn't know to prepare this __block storage for this passed variable.

这篇关于Swift:捕获逃脱被调用函数的闭包中的inout参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆