I am having issues with my app on visionOS. It works fine on iOS. The app is presenting a ImagePicker, I had tried converting to PhotoPicker and the behavior did not change.
The relevant code is in the EditGreetingCardView -
//
// Created by Michael Rowe on 1/2/24.
//
import AVKit
import SwiftData
import SwiftUI
struct EditGreetingCardView: View {
@Environment(\.modelContext) private var modelContext
@Environment(\.dismiss) private var dismiss
@Query(sort: \EventType.eventName) private var events: [EventType]
var greetingCard: GreetingCard?
private var editorTitle: String { greetingCard == nil ? "Add Greeting Card" : "Edit Greeting Card" }
@State var frontImageSelected: Image? = Image("frontImage")
@State var sourceType: UIImagePickerController.SourceType = .photoLibrary
@State var frontPhoto = false
@State var captureFrontImage = false
var eventTypePassed: EventType?
@State private var eventType: EventType?
@State private var cardName = ""
@State private var cardManufacturer = ""
@State private var cardURL = ""
@State private var cardUIImage: UIImage?
@State private var cameraNotAuthorized = false
@State private var isCameraPresented = false
@State private var newEvent = false
@AppStorage("walkthrough") var walkthrough = 1
init(eventTypePassed: EventType?) {
if let eventTypePassed {
_eventType = .init(initialValue: eventTypePassed)
}
}
init(greetingCard: GreetingCard?) {
self.greetingCard = greetingCard
_eventType = .init(initialValue: greetingCard?.eventType)
}
var body: some View {
NavigationStack {
Form {
Section("Occasion") {
Picker("Select Occasion", selection: $eventType) {
Text("Unknown Occasion")
.tag(Optional<EventType>.none) //basically added empty tag and it solve the case
if events.isEmpty == false {
Divider()
ForEach(events) { event in
Text(event.eventName)
.tag(Optional(event))
}
}
}
}
.foregroundColor(Color("AccentColor"))
Section("Card details") {
}
.foregroundColor(Color("AccentColor"))
Section("Card Image") {
HStack(alignment: .center){
Spacer()
ZStack {
Image(uiImage: cardUIImage ?? UIImage(named: "frontImage")!)
.resizable()
.aspectRatio(contentMode: .fit)
.shadow(radius: 10 )
Image(systemName: "camera.fill")
.foregroundColor(.white)
.font(.largeTitle)
.shadow(radius: 10)
.frame(width: 200)
.onTapGesture { self.frontPhoto = true }
.actionSheet(isPresented: $frontPhoto) { () -> ActionSheet in
#if !os(visionOS)
ActionSheet(
title: Text("Choose mode"),
message: Text("Select one."),
buttons: [
ActionSheet.Button.default(Text("Camera"), action: {
checkCameraAuthorization()
self.captureFrontImage.toggle()
self.sourceType = .camera
}),
ActionSheet.Button.default(Text("Photo Library"), action: {
self.captureFrontImage.toggle()
self.sourceType = .photoLibrary
}),
ActionSheet.Button.cancel()
]
)
#else
ActionSheet(
title: Text("Choose mode"),
message: Text("Select one."),
buttons: [
ActionSheet.Button.default(Text("Photo Library"), action: {
self.captureFrontImage.toggle()
self.sourceType = .photoLibrary }),
ActionSheet.Button.cancel()
]
)
#endif
}
.fullScreenCover(isPresented: $captureFrontImage) {
#if !os(visionOS)
ImagePicker(
sourceType: sourceType,
image: $frontImageSelected)
.interactiveDismissDisabled(true)
#else
ImagePicker(
image: $frontImageSelected)
.interactiveDismissDisabled(true)
#endif
}
}
.frame(width: 250, height: 250)
Spacer()
}
}
}
.alert(isPresented: $cameraNotAuthorized) {
Alert(
title: Text("Unable to access the Camera"),
message: Text("To enable access, go to Settings > Privacy > Camera and turn on Camera access for this app."),
primaryButton: .default(Text("Settings")) {
openSettings()
}
,
secondaryButton: .cancel()
)
}
.toolbar {
}
.onAppear {
}
.onChange(of: frontImageSelected) { oldValue, newValue in
cardUIImage = newValue?.asUIImage()
}
}
}
}