ios 变量以错误的顺序更新Swiftui

iyfjxgzm  于 2023-08-08  发布在  iOS
关注(0)|答案(1)|浏览(84)

我正在做一个列出一些照片的应用程序。当用户轻按照片时,会出现一张带有所选照片的工作表。
问题是:有时候我会点击第二张照片,我。即,索引= 1,并且第一张照片出现在工作表视图上。我不知道为什么,但问题也应该发生在其他指数,但到目前为止,只有第二张照片。下面是我的代码:

import SwiftUI

struct SheetView: View {
   
   @Binding var photo: String
   
   var body: some View {
       Text("photo title: " + photo)
   }
}

struct ContentView: View {
   
   @State private var selectedIndex: Int = 0
   @State private var photoEdition: Bool = false
   
   @State var photos: [String] = ["gigio", "lulu", "lucky"]
   
   private var photoToEdit: Binding<String> {
       
       .init(get: { () -> String in
           print("get", photos[selectedIndex], selectedIndex)
           return photos[selectedIndex]
       },
             set: { (newValue) in
           photos[selectedIndex] = newValue
           print("set", photos[selectedIndex], selectedIndex)
       })
   }
   
   var body: some View {
       
       VStack {
           ForEach(photos.indices, id:\.self) { index in
               Button(action: {
                   photoTapHandler(selectedIndex: index)
               }) {
                   Text(photos[index]).padding(10)
               }
           }
           
       } .sheet(isPresented: $photoEdition, content: {
           SheetView(photo: photoToEdit)
       })
   }
   
   private func photoTapHandler(selectedIndex: Int) {
       print("updating selected index to ", selectedIndex)
       self.selectedIndex = selectedIndex
       self.photoEdition = true
   }
}

字符串
我认为在photoTapHandler函数上,变量photoEditionselectedIndex被更改之前被设置为true。知道为什么吗这是执行日志。

updating selected index to  1
get gigio 0
get gigio 0


通过用下面的代码替换body,我不会得到错误。

var body: some View {
        
    VStack {
        ForEach(photos.indices, id:\.self) { index in
            Button(action: {
                photoTapHandler(selectedIndex: index)
            }) {
                Text(photos[index]).padding(10)
            }
        }
            
    }.onChange(of: selectedIndex) { selectedIndex in
        self.photoEdition = true
    }
    .sheet(isPresented: $photoEdition, content: {
            SheetView(photo: photoToEdit)
    })
}

private func photoTapHandler(selectedIndex: Int) {
    print("updating selected index to ", selectedIndex)
    self.selectedIndex = selectedIndex
    // self.photoEdition = true
}


提前感谢大家!:)

oymdgrw7

oymdgrw71#

SwiftUI是声明式的,所以操作顺序有点不同。仅仅因为一个操作先出现并不意味着它会先被执行。
在这种情况下,当您点击照片时,您希望selectedIndex在 * photoEdition之前更新 *。但是有一种可能性,状态更改(其中有两个)可能以不同的顺序异步执行。因此,当photoEdition == true时,Swift UI将重新渲染工作表视图,而photoToEdit可能仍然处于恢复旧的selectedIndex的操作中。错误的照片。
下面的photoEdition是 * 只有 * 更新时,selectedIndex肯定被更新。onChange修饰符确保photoEditionselectedIndex更新后更新。这并不是解决竞态条件的万灵药,但在本例中是有效的。下面我给出一个更快的答案。

var body: some View {
        
    VStack {
        ForEach(photos.indices, id:\.self) { index in
            Button(action: {
                photoTapHandler(selectedIndex: index)
            }) {
                Text(photos[index]).padding(10)
            }
        }
            
    }.onChange(of: selectedIndex) { selectedIndex in
        self.photoEdition = true
    }
    .sheet(isPresented: $photoEdition, content: {
            SheetView(photo: photoToEdit)
    })
}

private func photoTapHandler(selectedIndex: Int) {
    print("updating selected index to ", selectedIndex)
    self.selectedIndex = selectedIndex
    // self.photoEdition = true
}

字符串
这是一个更“快速”的方式来做的事情海事组织。

import SwiftUI

struct SheetView: View {
    @Binding var photo: String
    var body: some View {
        Text("photo title: " + photo)
    }
}

struct ContentView: View {
    struct Photo: Identifiable {
        var id: Int
        var name: String
    }
    
    @State var photos: [Photo] = [Photo(id: 0, name: "gigio"), Photo(id: 1, name: "lulu"), Photo(id: 2, name: "lucky")]
    @State var selectedPhoto: Photo? = nil
    
    var body: some View {
        VStack {
            ForEach(photos) { photo in
                Button(action: {
                    selectedPhoto = photo
                }) {
                    Text(photo.name).padding(10)
                }
            }
        }
        .sheet(item: $selectedPhoto) { photo in
            SheetView(photo: $selectedPhoto.name)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

相关问题