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()
}
}
}
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()
}
}