首页 > 解决方案 > 是否可以将 GeometryReader 的值传递给 @Observableobject

问题描述

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

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财产,但不知道如何做到这一点。

标签: swiftswiftui

解决方案


最简单的方法是在ObservableObject其中返回一个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()
    }
}

然后,您可以实现一个围绕GeometryReadertake的包装器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)
            }
        }
    }
}

推荐阅读