Avatar
@swift-4.2.4 // @escaping だけど同期的にクロージャが実行されるだけの関数 func run(_ body: @escaping () -> Void) { body() } // 値型を非同期的に更新するための機能を提供 struct Updater<Object: AnyObject, Target> { let object: Object let keyPath: ReferenceWritableKeyPath<Object, Target> func update(_ body: (inout Target) throws -> Void) rethrows { try body(&object[keyPath: keyPath]) } } // 値型、これの状態を @escaping をまたいで更新したい struct FooState { var a: Int = 0 mutating func incrementA<Object: AnyObject>(with updater: Updater<Object, FooState>) { run { // @escaping なのでこの中では `self` を更新できない updater.update { state in // Updater を使って更新 state.a += 1 } } } } // FooState を保持する参照型 class Foo { var state: FooState = FooState() func bar() { state.incrementA(with: Updater<Foo, FooState>(object: self, keyPath: \Foo.state)) } } let foo = Foo() foo.bar() print(foo.state.a)