iOS14: Found nil while implicitly unwrapping optional

Hello,

I am running my app written using SwiftUI on iOS 14 and the app crashes because of unexpectedly nil while unwrapping optional.

This occurs when I try to share an image using its local URL in the Share Sheet.

The puzzling part is that that it works perfectly on iOS 13.

I am still new to development, so any help will be appreciated! Thanks in advance.

Code Block
struct ContentView: View {
        @State private var imageURL: URL?
@State private var isShareSheetPresented = false
        
        var body: some View {
            ScrollView(.vertical) {
                VStack{
                    Text("Test")
            }
            .navigationBarItems(trailing: Button(action: {
                writeImageToDisk()
                isShareSheetPresented.toggle()
            }) {
                Image(systemName: "square.and.arrow.up")
            }.sheet(isPresented: self.$isShareSheetPresented) {
                ShareSheet(photo: imageURL!)
            })
        }
        func writeImageToDisk() {
            imageURL = (UIApplication.shared.windows[0].rootViewController?.view!.getImage())!
print(imageURL!)
        }
}
// getImage is a function that returns an URL
// imageURL is always getting printed successfully
// Here is a sample of print(imageURL!) from console: file:///var/mobile/Containers/Data/Application/740E2665-8D68-4864-9E48-99E4E25D2985/Documents/Test%20Image.png
//


Code Block
struct ShareSheet: UIViewControllerRepresentable {
    let photo: URL
          
    func makeUIViewController(context: Context) -> UIActivityViewController {
        let activityItems: [Any] = [photo]
        
        let controller = UIActivityViewController(
            activityItems: activityItems,
            applicationActivities: nil)
        
        return controller
    }
      
    func updateUIViewController(_ vc: UIActivityViewController, context: Context) {
    }
}


Answered by OOPer in 631067022
Seems you have hit some critical point where SwiftUI has changed its detailed behavior.

Captured @State variables may not work in some context in iOS 14.

You may try something like this:
Code Block
struct ShareSheet: UIViewControllerRepresentable {
@Binding var photo: URL? //<-
func makeUIViewController(context: Context) -> UIActivityViewController {
let activityItems: [Any] = photo.map {[$0]} ?? [] //<-
//...
}
//...
}

and
Code Block
struct ContentView: View {
@State private var imageURL: URL?
@State private var isShareSheetPresented = false
var body: some View {
ScrollView(.vertical) {
VStack{
Text("Test")
}
.navigationBarItems(trailing: Button(action: {
self.writeImageToDisk()
self.isShareSheetPresented.toggle()
}) {
Image(systemName: "square.and.arrow.up")
}.sheet(isPresented: self.$isShareSheetPresented) {
ShareSheet(photo: self.$imageURL) //<-
})
}
}
//...
}



By the way, this line in your code:
Code Block
imageURL = (UIApplication.shared.windows[0].rootViewController?.view!.getImage())!

is far from recommended.
It depends on implementation details of other parts of the app, and uses many forced-unwrappings (!).

It is not the cause of your issue now, but is a possible risk that may cause some problems.
Accepted Answer
Seems you have hit some critical point where SwiftUI has changed its detailed behavior.

Captured @State variables may not work in some context in iOS 14.

You may try something like this:
Code Block
struct ShareSheet: UIViewControllerRepresentable {
@Binding var photo: URL? //<-
func makeUIViewController(context: Context) -> UIActivityViewController {
let activityItems: [Any] = photo.map {[$0]} ?? [] //<-
//...
}
//...
}

and
Code Block
struct ContentView: View {
@State private var imageURL: URL?
@State private var isShareSheetPresented = false
var body: some View {
ScrollView(.vertical) {
VStack{
Text("Test")
}
.navigationBarItems(trailing: Button(action: {
self.writeImageToDisk()
self.isShareSheetPresented.toggle()
}) {
Image(systemName: "square.and.arrow.up")
}.sheet(isPresented: self.$isShareSheetPresented) {
ShareSheet(photo: self.$imageURL) //<-
})
}
}
//...
}



By the way, this line in your code:
Code Block
imageURL = (UIApplication.shared.windows[0].rootViewController?.view!.getImage())!

is far from recommended.
It depends on implementation details of other parts of the app, and uses many forced-unwrappings (!).

It is not the cause of your issue now, but is a possible risk that may cause some problems.
@OOper Thank you sooo much! This finally solved my issue.

I'm curious to learn more, is there more I can read on the recent changes in SwiftUI?

P.S: Thank you for your other comment on the force-unwrapping, I will try to avoid them by using try? or guard

is there more I can read on the recent changes in SwiftUI? 

Sorry, but I do not know any single article or site collecting such info. We need to find and follow some reports in the dev forums or in other sites, such as you have written in this thread. Thanks for sharing your experience.
iOS14: Found nil while implicitly unwrapping optional
 
 
Q