how to pass an img value between 2 views?

Viewed 41

I am trying to pass a @Binding UI Image from an Image picker to another view through a sheet. I tried to use the OnDismiss() parameter but it did not work, even tried ondisapper(). What i want is that, when i press a button, it should open up the image picker directly. When a user has selected an image it should take that image and navigate to another view and show the image. This is the code im trying but is not working : -

NavigationBar.swift

import SwiftUI

struct NavigationBar: View {
    var title = ""
    @Binding var hasScrolled: Bool
    @State var showUploadPost = false
    @State var imagePickerPresented = false
    @State private var selectedImage: UIImage?
    @State var postImage: Image?
//    @State var showAccount = false
    @State var captionText = ""
    
    var body: some View {
        ZStack {
            Color.clear
                .background(.ultraThinMaterial)
                .blur(radius: 10)
                .opacity(hasScrolled ? 1 : 0)
            
            Text(title)
                .animatableFont(size: hasScrolled ? 22 : 34, weight: .bold)
                .frame(maxWidth: .infinity, alignment: .leading)
                .padding(.leading, 20)
                .padding(.top, 20)
                .offset(y: hasScrolled ? -4 : 0)
            
            HStack(spacing: 16) {
                Button {
                    imagePickerPresented = true
                } label: {
                    Image(systemName: "plus.square")
                        .font(.title3.weight(.bold))
                        .frame(width: 46, height: 46)
                        .foregroundColor(.secondary)
                        .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 14, style: .continuous))
                    .strokeStyle(cornerRadius: 14)
                }
               .sheet(isPresented: $imagePickerPresented, onDismiss: {
                    newPostView(image: $selectedImage) // this is the problem
                }) {
                    ImagePicker(image: $selectedImage)
                } 
                
            .frame(maxWidth: .infinity, alignment: .trailing)
            .padding(.trailing, 20)
            .padding(.top, 20)
            .offset(y: hasScrolled ? -4 : 0)
        }
        .frame(height: hasScrolled ? 44 : 70)
        .frame(maxHeight: .infinity, alignment: .top)
    }
}

extension NavigationBar {
    func loadImage() {
        guard let selectedImage = selectedImage else { return }
        postImage = Image(uiImage: selectedImage)
    }
}

newPostView.swift

import SwiftUI

struct newPostView: View {
    @Binding var image: UIImage?
    
    var body: some View {
        VStack {
            Text("hi")
        }
    }
}

ImagePicker.swift


struct ImagePicker: UIViewControllerRepresentable {
    @Binding var image: UIImage?
    @Environment(\.presentationMode) var mode
    
    func makeUIViewController(context: Context) -> some UIViewController {
        let picker = UIImagePickerController()
        picker.delegate = context.coordinator
        return picker
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
        
    }
    
    class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
        let parent: ImagePicker
        
        init(_ parent: ImagePicker) {
            self.parent = parent
        }
        
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            guard let image = info[.originalImage] as? UIImage else { return }
            self.parent.image = image
            self.parent.mode.wrappedValue.dismiss()
        }
    }
}
1 Answers

Solution 1: Simply use hidden navigation bar technique to push it to another view on selecting the Image.

struct NavigationBar: View {
    @State var imagePickerPresented = false
    @State private var selectedImage: UIImage?
    @State private var newPost = false

    var body: some View {
        VStack {
            Text("Hello, World!")
            Button {
                imagePickerPresented = true
            } label: {
                Image(systemName: "plus.square")
                    .font(.title3.weight(.bold))
                    .frame(width: 46, height: 46)
                    .foregroundColor(.secondary)
                    .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 14, style: .continuous))
            }
            .sheet(isPresented: $imagePickerPresented, onDismiss: {
                newPost.toggle() //1 <--- FIX
            }) {
                ImagePicker(image: $selectedImage)
            }
            
            // 2 FIX ⬇️
            // Hide Navigation Link
            NavigationLink("NewPostView", isActive: $newPost) {
                newPostView(image: $selectedImage)
            }.hidden()
        }
    }
}

Note: This works when the NavigationBar is inside the NavigationView. For example -

struct ContenView: View {
    var body: some View {
        NavigationView{
            NavigationBar()
        }
    }
}

Solution 2: If you don't want Navigation to the newPostView, use like this

struct NavigationBar: View {
    @State var imagePickerPresented = false
    @State private var selectedImage: UIImage?
    @State private var newPost = false

    var body: some View {
        VStack {
            Text("Hello, World!")
            Button {
                imagePickerPresented = true
            } label: {
                Image(systemName: "plus.square")
                    .font(.title3.weight(.bold))
                    .frame(width: 46, height: 46)
                    .foregroundColor(.secondary)
                    .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 14, style: .continuous))
            }
            .sheet(isPresented: $imagePickerPresented, onDismiss: {
                newPost.toggle() //1 <--- FIX
            }) {
                ImagePicker(image: $selectedImage)
            }
            .fullScreenCover(
              isPresented: $newPost) {
                  newPostView(image: $selectedImage)
            }
        }
    }
}

struct ContentView: View {
    @State var imagePickerPresented = false
    @State private var selectedImage: UIImage?
    @State private var newPost = false
    
    var body: some View {
        NavigationBar()
    }
}
Related