Я попытался написать класс «редактор», который мог бы сохранить ссылку на свойство для другого объекта для последующей мутации. Я сначала написал класс редактора, чтобы получить закрытие для чтения, и закрытие для записи. Это сработало. Затем я попытался передать рассматриваемый параметр ссылкой (inout), а затем сгенерировал пару геттер/сеттер. Это не сработало. Документы Swift говорят (перефразируя), что Свифт указывает, когда копировать, а когда нет. Я думаю, что я против непредсказуемости этого ограничения, но думал, что я поставил бы вопрос точно так же.Swift: Захват inout параметра в замыканиях, которые вызывают вызванную функцию
В качестве альтернативы можно ли получить функцию карри для индивидуального геттера и сеттера?
Мой код:
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
Спасибо!
Возможно, мне что-то не хватает, кажется, что есть две проблемы: семантика семантики закрытия и время жизни объекта. К последнему моменту вы уже можете создать класс (ссылочный тип) в стеке и вызвать функцию, которая хранит ее вне времени жизни функции. В первую очередь, однако, автоматическая копия семантики Swift, похоже, заботится о проблеме с блоком, они просто не играют вместе. То, что я действительно хочу, - это получить теневой геттер/сеттер. Надеюсь, в какой-то момент они добавят синтаксис. Спасибо за ваш ответ. –
@chrisco: речь идет не о «объектах» (на которые указывают переменные ссылочных типов), а сами * переменные * (либо переменные типа значения, либо ссылочный тип, это не имеет значения). A * локальная переменная *, независимо от Objective-C или Swift, имеет только время жизни области, в которой она была объявлена, если только она не объявлена '__block' в Objective-C или не используется в закрытии в Swift, и в этом случае компилятор сохраняет его таким образом, что он может жить дольше. – newacct
@newacct ваше объяснение, похоже, имеет отверстие в нем, потому что __block требуется только для значений, которые будут мутированы. Другие значения захватываются без специальной аннотации и вне зависимости от их кадров стека без проблем. В общем, то, что вы сказали, похоже, имеет большой смысл. Моя проблема в том, что эта функциональность необходима. Для правильного хранения этих значений должно быть ключевое слово swift, чтобы они могли быть мутированы таким образом. – BTRUE