代码之家  ›  专栏  ›  技术社区  ›  pistacchio

在Mac上,无论物理布局如何,都可以检测键盘上按下的键

  •  0
  • pistacchio  · 技术社区  · 4 年前

    以下代码是从我在一个更大的应用程序中面临的问题中提取的最小可重复示例。我尝试使用以下代码:

    1. 看一看( Container )具有可观察对象的可观察阵列
    2. 通过数组中的索引访问其中一个对象
    3. 更改观察对象实例的属性
    4. 拥有儿童视角( ObjectVisualizer )传递的数据反映了通过用更改的属性重新绘制数组对对象所做的更改

    问题是,对任何对象的任何更改都不会反映出来。如何使其发挥作用?

    class MyObservedObject: Hashable, Equatable, ObservableObject {
        @Published var text: String
        
        init(_ text: String) {
            self.text = text
        }
        
        static func == (lhs: MyObservedObject, rhs: MyObservedObject) -> Bool {
            return lhs.text == rhs.text
        }
        
        func hash(into hasher: inout Hasher) {
            hasher.combine(self.text)
        }
        
        static func newSet() -> [MyObservedObject] {
            return [
                MyObservedObject("a"),
                MyObservedObject("b"),
                MyObservedObject("c"),
            ]
        }
    }
    
    class ContainerData: ObservableObject {
        @Published var objects = MyObservedObject.newSet()
    }
    
    struct Container: View {
        @ObservedObject private var data = ContainerData()
        
        var body: some View {
            ObjectVisualizer(data.objects)
            
            Button("Click me") {
                self.data.objects[2].text = "Changed"
            }
        }
    }
        
    struct ObjectVisualizer: View {
        private var objects: [MyObservedObject]
        
        init(_ objects: [MyObservedObject]) {
            self.objects = objects
        }
        
        var body: some View {
            ForEach(self.objects, id: \.self) {obj in
                Text(obj.text)
            }
        }
    }
        
    struct ContentView: View {
        var body: some View {
            Container()
        }
    }
    
    0 回复  |  直到 4 年前
        1
  •  2
  •   jnpdx    4 年前

    预先警告:

    这将是 更容易 如果你的模型是一个结构体而不是ObservableObject,你基本上可以免费获得所有这些行为。但是,我假设你的应用程序不能以这种方式构建是有原因的。话虽如此,试图用ObservableObjects阵列做到这一点是一场艰苦的战斗,我认为这是在与SwiftUI的设计工作方式作斗争。然而,这个解决方案似乎确实有效。


    
    import Combine
    
    class MyObservedObject: Hashable, Equatable, ObservableObject {
        let id = UUID()
        @Published var text: String
        
        init(_ text: String) {
            self.text = text
        }
        
        static func == (lhs: MyObservedObject, rhs: MyObservedObject) -> Bool {
            return lhs.id == rhs.id
        }
        
        func hash(into hasher: inout Hasher) {
            hasher.combine(self.id)
        }
        
        static func newSet() -> [MyObservedObject] {
            return [
                MyObservedObject("a"),
                MyObservedObject("b"),
                MyObservedObject("c"),
            ]
        }
    }
    
    class ContainerData: ObservableObject {
        @Published var objects = MyObservedObject.newSet()
    }
    
    struct Container: View {
        @ObservedObject private var data = ContainerData()
        
        var body: some View {
            VStack {
                ObjectVisualizer(data.objects)
                
                Button("Click me") {
                    self.data.objects[2].text = "Changed"
                    data.objectWillChange.send()
                }
            }
        }
    }
    
    class MyObservedObjectWrapper : ObservableObject {
        var objects: [MyObservedObject]
        
        init(objects: [MyObservedObject]) {
            self.objects = objects
        }
    }
    
    struct ObjectVisualizer: View {
        @ObservedObject var wrapper : MyObservedObjectWrapper
        
        init(_ objects: [MyObservedObject]) {
            self.wrapper = MyObservedObjectWrapper(objects: objects)
        }
        
        var body: some View {
            ForEach(wrapper.objects, id: \.id) {obj in
                Text(obj.text)
            }
        }
    }
    
    struct ContentView: View {
        var body: some View {
            Container()
        }
    }
    
    

    发生了什么:

    1. MyObservedObject 具有唯一的ID,而不是依赖于 text 现场。

    2. 当按下“点击我”按钮时,它必须手动呼叫 objectWillChange.send() 因为否则ObservableObject不知道它正在更新(因为您正在修改引用类型的数组而不是值类型。

    3. 这个 ObjectVisualizer 视图不想只使用传入的引用类型数组重新呈现。因此,我将它们放在一个包装器对象中。这似乎触发了中所需的重新渲染 ForEach


    做这样的事情不值得重构以获得结构模型吗?在我看来,可能不会,但当然,我对你的具体情况没有更多的了解。