在一个位置更改图像时,如何使其反映SwiftUI中其他位置的更改?

在一个位置更改图像时,如何使其反映SwiftUI中其他位置的更改?,swiftui,Swiftui,我有两个问题 我有一个图像作为按钮,所以当你点击它时,你可以从你的图像卷中选择一个图像。当我转到另一个视图,然后返回时,图像消失了。当我在SwiftUI中更改视图时,如何防止它消失 如何将其链接到应用程序中的其他UIImages,以便当您更改某个位置的图像时,它会反映其他位置的更改?现在顶部的图像是硬编码的,但我希望它能反映较小的图像显示的内容。我已经在下面添加了一张图片来展示我正在谈论的内容,或者你可以查看它的视频 这是我的密码: import SwiftUI struct ImagePi

我有两个问题

  • 我有一个图像作为按钮,所以当你点击它时,你可以从你的图像卷中选择一个图像。当我转到另一个视图,然后返回时,图像消失了。当我在SwiftUI中更改视图时,如何防止它消失
  • 如何将其链接到应用程序中的其他UIImages,以便当您更改某个位置的图像时,它会反映其他位置的更改?现在顶部的图像是硬编码的,但我希望它能反映较小的图像显示的内容。我已经在下面添加了一张图片来展示我正在谈论的内容,或者你可以查看它的视频
  • 这是我的密码:

    import SwiftUI
    
    struct ImagePicker: View {
    
        @State var isShowingImagePicker = false
    
        @State var imageInBlackCircle = UIImage()
    
        var body: some View {
            VStack {
                Button(action: {
                    self.isShowingImagePicker.toggle()
                }) {
                    Image(uiImage: imageInBlackCircle)
                        .renderingMode(.original)
                        .resizable()
                        .scaledToFill()
                        .clipShape(Circle())
                        .overlay(Circle() .stroke(Color.black, lineWidth: 1))
                        .shadow(color: .black, radius: 3, x: 0, y: 3)
                        .frame(width: 60.0, height: 70.0)
                        .padding(.trailing, 20)
    
                        .sheet(isPresented: $isShowingImagePicker, content: {
                            ImagePickerView(isPresented: self.$isShowingImagePicker, selectedImage: self.$imageInBlackCircle)
                        })
                }
            }
        }
    
        struct ImagePickerView: UIViewControllerRepresentable {
    
            @Binding var isPresented: Bool
            @Binding var selectedImage: UIImage
    
            func makeUIViewController(context:
                UIViewControllerRepresentableContext<ImagePickerView>) ->
                UIViewController {
                    let controller = UIImagePickerController()
                    controller.delegate = context.coordinator
                    return controller
            }
    
            func makeCoordinator() -> ImagePickerView.Coordinator {
                return Coordinator(parent: self)
            }
    
            class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    
                let parent: ImagePickerView
                init(parent: ImagePickerView) {
                    self.parent = parent
                }
    
                func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
                    if let selectedImageFromPicker = info[.originalImage] as? UIImage {
                        print(selectedImageFromPicker)
                        self.parent.selectedImage = selectedImageFromPicker
                    }
    
                    self.parent.isPresented = false
                }
            }
    
    
            func updateUIViewController(_ uiViewController: ImagePickerView.UIViewControllerType, context: UIViewControllerRepresentableContext<ImagePickerView>) {
    
            }
        }
    
        struct ImagePicker_Previews: PreviewProvider {
            static var previews: some View {
                ImagePicker()
            }
        }
    }
    
    
    导入快捷界面
    结构图像选择器:视图{
    @状态变量isShowingImagePicker=false
    @状态变量imageInBlackCircle=UIImage()
    var body:一些观点{
    VStack{
    按钮(操作:{
    self.isShowingImagePicker.toggle()文件
    }) {
    图像(uiImage:imageInBlackCircle)
    .renderingMode(.original)
    .可调整大小()
    .scaledToFill()
    .clipShape(圆())
    .overlay(圆圈().stroke(颜色.黑色,线宽:1))
    .阴影(颜色:黑色,半径:3,x:0,y:3)
    .框架(宽度:60.0,高度:70.0)
    .padding(.training,20)
    .sheet(显示:$isShowingImagePicker,内容:{
    ImagePickerView(显示:self.$isShowingImagePicker,选择图像:self.$imageInBlackCircle)
    })
    }
    }
    }
    结构ImagePickerView:UIViewControllerRepresentable{
    @显示绑定变量:Bool
    @绑定变量SelecteImage:UIImage
    func makeUIViewController(上下文:
    UIViewControllerRepresentableContext)->
    UIViewController{
    let controller=UIImagePickerController()
    controller.delegate=context.coordinator
    返回控制器
    }
    func makeCoordinator()->ImagePickerView.Coordinator{
    退货协调员(家长:本人)
    }
    类协调器:NSObject、UIImagePickerControllerDelegate、UINavigationControllerDelegate{
    让父对象:ImagePickerView
    初始化(父项:ImagePickerView){
    self.parent=parent
    }
    func imagePickerController(picker:UIImagePickerController,didFinishPickingMediaWithInfo:[UIImagePickerController.InfoKey:Any]){
    如果让我们选择dImageFromPicker=info[.originalImage]作为?UIImage{
    打印(从选择器中选择图像)
    self.parent.selectedImage=selectedimagefromfrompicker
    }
    self.parent.isPresented=false
    }
    }
    func updateUIViewController(uUIViewController:ImagePickerView.UIViewControllerType,上下文:UIViewControllerRepresentableContext){
    }
    }
    结构ImagePicker\u预览:PreviewProvider{
    静态var预览:一些视图{
    图像选择器()
    }
    }
    }
    
    因此,您现在知道了
    @State
    的用法。它们是特殊类型的属性,这些属性有助于
    SwiftUI
    视图在其值发生任何更改时重新加载。这确保了同步。所以,如果你需要把这个财产和其他地方联系起来,你需要绕过这个财产,对吗?但出于设计:

    @State
    非常适合于属于特定视图的简单属性,并且永远不会在该视图之外使用,因此,将这些属性标记为私有非常重要,以重新强化这样一种理念,即这种状态是专门设计的,永远不会脱离其视图


    那么我们有什么?注意:

    对于更复杂的属性–当您要使用的自定义类型可能具有多个属性和方法,或者可能在多个视图中共享时–您应该使用
    @ObservedObject

    你可以从中读到更多

    上述说法有意义吗?如果是,则需要此
    @ObservedObject
    。让我们看看我们是如何做到这一点的

    您声明的对象符合
    observeObject
    。您使用
    @Published
    包装器标记这些属性,以便所述
    observeObject
    的任何实例都会收到对该属性所做更改的通知

    import Combine
    import UIKit
    
    class UserViewModel: ObservableObject {
        @Published var image = UIImage()
    }
    
    现在,您需要这个对象的某个实例,以便可以观察它的状态。这就是您将使用
    @ObservedObject
    包装器的地方

    struct ImagePicker: View {
        @State private var isShowingImagePicker = false // make this private
        @State private var isShowingDetailView = false // make this private
    
        @ObservedObject var viewModel = UserViewModel() // either you initialize this here, 
                                                        // or inject this from somewhere else
    }
    
    然后,在初始化其他视图时,为了显示/呈现,只需传递
    @ObservedObject
    属性。比如:

    NavigationLink(destination: DetailView(userViewModel: viewModel), isActive: $isShowingDetailView) {
        Text("Detail")
    }
    
    您的
    DetailView
    有点像:

    struct DetailView: View {
        var userViewModel: UserViewModel // you may need to declare this as @ObservedObject as well if you are required to manipulate state of UserViewModel from this view
        var body: some View {
            Image(uiImage: userViewModel.image)
                .navigationBarTitle(Text("Detail"), displayMode: .inline)
        }
    }
    

    对于您的简单案例,这应该足够了。但是,如果您需要从视图层次结构的任何位置访问有状态对象,您可能需要查看
    @EnvironmentObject

    是一个与您的配置稍有不同的演示实现。您可以去看看我得到了什么。当您点击profile选项卡并在那里更改图像时,我希望它在同一屏幕上以及在home选项卡上更改。此外,我希望它能保持不变,而不是在你更改标签或关闭应用程序时消失。我尝试了你的建议,但我无法让它对我起作用。还有你的评论,我希望它保持不变,而不是在你改变标签时消失。如果你已经研究了我对你的简单案例的最后一行所说的话,这应该足够了。但是,如果您需要从视图层次结构的任何位置访问有状态对象,您可能需要查看
    @EnvironmentObject
    。一旦你找到了我之前评论的解决方案