首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在geometryReader中设置@State

在geometryReader中设置@State
EN

Stack Overflow用户
提问于 2020-04-04 19:21:52
回答 3查看 723关注 0票数 2

如何在geometryReader中设置@State变量

这是我的代码

代码语言:javascript
复制
@State var isTest:Int = 0

var body: some View {
    VStack{
        ForEach(self.test, id: \.id) { Test in
            VStack{
                GeometryReader { geometry in
                    self.isTest = 1

我尝试了一个函数,但不起作用

代码语言:javascript
复制
@State var isTest:Int = 0

func testValue(){
    self.isTest = 1
}

var body: some View {
    VStack{
        ForEach(self.test, id: \.id) { Test in
            VStack{
                GeometryReader { geometry in
                    testValue()

有什么想法吗?谢谢!

EN

回答 3

Stack Overflow用户

发布于 2020-10-29 14:42:56

昨天我也遇到了类似的问题。但是我试图从GeometryReader内部传递一个值。

我尝试了几种方法,但都不起作用。当我使用@State var声明变量时,编译器再次抱怨说,在更新期间修改视图将使其成为未定义的视图。

当我试图仅使用var声明一个变量时,编译器只告诉我它是不可变的。

然后,我试着把它存储到我的@EnvironmentObject上。我刚刚得到了一个死循环。

所以,我最后的希望是使用通知的方式以及它是如何工作的。但我不知道这是否是标准的实现方式。

代码语言:javascript
复制
@State private var viewPositionY:CGFloat = 0

首先,通过通知发布值frame.origin.y

代码语言:javascript
复制
 GeometryReader{ geometry -> Text in
        let frame = geometry.frame(in: CoordinateSpace.global)
        NotificationCenter.default.post(name: Notification.Name("channelBlahblahblah"), object:nil, userInfo:["dict":frame.origin.y])
        return Text("My View Title")
 }

然后声明一个发布者来接收通知。

代码语言:javascript
复制
private let myPublisher = NotificationCenter.default.publisher(for: Notification.Name("channelBlahblahblah"))

最后,使用.onReceive修饰符接收通知。

代码语言:javascript
复制
.onReceive(myPublisher) { (output) in
           
   viewPositionY = output.userInfo!["dict"] as! CGFloat
   //you can do you business here
}
票数 3
EN

Stack Overflow用户

发布于 2021-03-04 16:34:02

虽然将代码放入函数是一个很好的做法,但可能会遇到另一个问题,那就是在更新阶段更改@State变量:[SwiftUI] Modifying state during view update, this will cause undefined behavior

在视图更新阶段之后使用NotificationCenter移动@State变量更新可能会有所帮助,但可以使用更简单的解决方案,比如使用DispatchQueue在呈现阶段之后立即执行变量更新。

代码语言:javascript
复制
@State var windowSize = CGSize()

func useProxy(_ geometry: GeometryProxy) -> some View {

    DispatchQueue.main.async {
        self.windowSize = geometry.size
    }

    return EmptyView()
}

var body: some View {

    return GeometryReader { geometry in
        self.useProxy(geometry)    

        Text("Hello SwiftUI")        
    }
}
票数 1
EN

Stack Overflow用户

发布于 2021-06-06 11:40:04

因此,在GeometryReader中更新@State是完全可能的。解决方案很简单。然而,有一个警告:

你可能会得到一个无限循环的(没什么麻烦的,我将在这里给出一个解决方案)

您只需要一个DispatchQueue.main.async,并在GeometryReader中显式声明视图的类型。如果您执行下面的视图(不要忘记停止它),您将看到它从未停止更新Text的值。

不是最终的解决方案:

代码语言:javascript
复制
struct GenericList: View {
    @State var timesCalled = 0

    var body: some View {
        GeometryReader { geometry -> Text in
            DispatchQueue.main.async {
                timesCalled += 1 // infinite loop
            }
            return Text("\(timesCalled)")
        }
    }
}

这是因为视图将“绘制”GeometryReader,这将更新视图的@State。因此,新的@State会使视图无效,从而导致视图被重新绘制。因此返回到第一步(绘制GeometryReader并更新状态)。

要解决这个问题,您需要在GeometryReader的绘制中添加一些约束。不是在GeometryReader中返回视图,而是绘制它,然后添加GeometryReader作为透明覆盖或背景。这将具有相同的效果,但您将能够在演示文稿中添加约束。

就我个人而言,我更喜欢使用覆盖,因为你可以添加你想要的数量。请注意,覆盖图不允许在其中包含if else,但可以调用函数。这就是为什么下面有func geometryReader()的原因。另一件事是,为了返回不同类型的视图,您需要在它之前添加@ViewBuilder

在这段代码中,GeometryReader只被调用一次,您将更新@State。

最终解决方案:

代码语言:javascript
复制
struct GenericList: View {
    @State var timesCalled = 0
    
    @ViewBuilder
    func geometryReader() -> some View {
        if timesCalled < 1 {
            GeometryReader { geometry -> Color in
                DispatchQueue.main.async {
                    timesCalled += 1
                }
                return Color.clear
            }
        } else {
            EmptyView()
        }
    }

    var body: some View {
        Text("\(timesCalled)")
            .overlay(geometryReader())
    }
}

注意:您不需要放置相同的约束,例如,in my case,我想使用拖动手势移动视图。因此,我将约束设置为在用户按下时启动,并在用户结束拖动手势时停止。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61027327

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档