Avatar
$foo.readOnly.a できた。この方法絶対ダメだけどw import SwiftUI extension ObservedObject.Wrapper { var readOnly: ReadOnly { let object: ObjectType = unsafeBitCast(self, to: ObjectType.self) return ReadOnly(object) } @dynamicMemberLookup struct ReadOnly { private let object: ObjectType init(_ object: ObjectType) { self.object = object } subscript<Subject>(dynamicMember keyPath: KeyPath<ObjectType, Subject>) -> Binding<Subject> { Binding<Subject>( get: { self.object[keyPath: keyPath] }, set: { _ in assertionFailure("Read-only") } ) } } }
3:04 PM
Wrapper はどう考えても元のオブジェクトをラップしてるだけだろうと考えて unsafeBitCast したら動いたw
3:10 PM
今やりたいのは、↓の Foo のような型に対して @ObservedObject var foo: Foo を作って、 $foo.readOnly.a のようにして read-only な片方向のバインディングを作りたいということです。 import Combine class Foo: ObservableObject { @Published private(set) var a: Int = 0 func incrementA() { a += 1 } }
3:12 PM
今は incrementA が露出してるけど、アップデートのための関数は生成者や internal にしか暴露されないとかもあり得る。そうでなくても、↑の incrementA のようにアップデートの方法を限定したいからプロパティが private(set) になるケースもあって、そのようなケースでもバインディングしたいというニーズも考えられる。