是否可以将GeometryReader的值传递给@Observableobject

时间:2019-08-21 18:23:13

标签: swift swiftui

我需要根据设备的尺寸和屏幕的宽度进行计算。

struct TranslatorView: View {

@ObservedObject var settings = TranslationViewModel(spacing: 4, charSize: 20)
var body: some View {
    GeometryReader { geometry in
        VStack{
             TextField("Enter your name", text:self.$settings.translateString)               
        }

    }
}
}

我的ObservableObject可以在下面看到

class TranslationViewModel: ObservableObject {
    @Published var translateString  = ""
    var ScreenSize : CGFloat = 0
    var spacing : CGFloat = 4
    var charSize : CGFloat = 20

    init(spacing: CGFloat, charSize : CGFloat) {
         self.spacing = spacing
        self.charSize = charSize
     }
}

我需要一种方法将geometry.size.width传递到我的ScreenSize属性,但不知道如何执行此操作。

2 个答案:

答案 0 :(得分:2)

最简单的方法是在ObservableObject中包含setter方法,该方法将返回EmptyView

import SwiftUI

struct TranslatorView: View {
    @ObservedObject var settings = TranslationViewModel(spacing: 4, charSize: 20)
    var body: some View {
        GeometryReader { geometry in
            VStack{
                self.settings.passWidth(geometry: geometry)
                TextField("Enter your name", text:self.$settings.translateString)
            }

        }
    }
}

class TranslationViewModel: ObservableObject {
    @Published var translateString  = ""
    var ScreenSize : CGFloat = 0
    var spacing : CGFloat = 4
    var charSize : CGFloat = 20

    init(spacing: CGFloat, charSize : CGFloat) {
        self.spacing = spacing
        self.charSize = charSize
    }

    func passWidth(geometry: GeometryProxy) -> EmptyView {
        self.ScreenSize = geometry.size.width
        return EmptyView()
    }
}

然后,您可以使用GeometryReader来实现content: () -> Content的包装,并在每次GeometryReader重新呈现时执行一个闭包,以便您可以更新所需的内容。

import SwiftUI

struct TranslatorView: View {
    @ObservedObject var settings = TranslationViewModel(spacing: 4, charSize: 20)
    var body: some View {
        GeometryReaderEasy(callback: {
            self.settings.ScreenSize = $0.size.width
        }) { geometry in
            TextField("Enter your name", text:self.$settings.translateString)
        }
    }
}

struct GeometryReaderEasy<Content: View>: View {
    var callback: (GeometryProxy) -> ()
    var content: (GeometryProxy) -> (Content)

    private func setGeometry(geometry: GeometryProxy) -> EmptyView {
        callback(geometry)
        return EmptyView()
    }

    var body: some View {
        GeometryReader { geometry in
            VStack{
                self.setGeometry(geometry: geometry)
                self.content(geometry)
            }
        }
    }
}

答案 1 :(得分:1)

您可以在View上使用一个简单的扩展名,以在构建视图时允许任意代码执行。

extension View {
    func execute(_ closure: () -> Void) -> Self {
        closure()
        return self
    }
}

然后

var body: some View {
    GeometryReader { proxy
        Color.clear.execute {
            self.myObject.useProxy(proxy)
        }
    }
}