Mijick / Popups

Popups, popovers, sheets, alerts, toasts, banners, (...) presentation made simple. Written with and for SwiftUI.
Apache License 2.0
1.38k stars 61 forks source link

[BUG] When editing the TextField, a Popup error occurs: "Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value" #158

Closed snow-xf closed 1 week ago

snow-xf commented 2 weeks ago
import SwiftUI
import MijickPopups

@main
struct TestApp: App {
    @StateObject var viewModel:TestViewModel = TestViewModel()
    var body: some Scene {
        WindowGroup {
            ContentView()
                .registerPopups()
                .environmentObject(viewModel)
        }
    }
}

class TestViewModel:ObservableObject{
    @Published var text: String = ""
}

struct ContentView: View {
    var body: some View {
        NavigationStack{
            List{
                NavigationLink {
                    NextView()
                } label: {
                    Text("Next")
                }
            }
        }
    }
}

struct NextView:View {
    @EnvironmentObject var viewModel:TestViewModel
    @FocusState private var isInputFocused:Bool
    var body: some View{
        List{
            /// When editing the TextField, a Popup error occurs: "Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value"
            TextField("Edit Text", text: $viewModel.text,onCommit: {
                isInputFocused = false
            })
            .focused($isInputFocused)

            Button {
                isInputFocused = false
                Popup().present()
            } label: {
                Text("Test Popup")
            }
        }
    }
}

struct Popup:BottomPopup {
    var body: some View{
        Text("Test")
            .padding()
            .onTapGesture {
                dismissLastPopup()
            }
    }
    func configurePopup(config: LocalConfig.Vertical.Bottom) -> LocalConfig.Vertical.Bottom {
        config.tapOutsideToDismissPopup(true)
    }
}

截屏2024-11-13 10 06 18

FulcrumOne commented 1 week ago

Thanks for the report. The branch patch-4.0.0 should be finished by Saturday, and the problem should be resolved there. I'll let you know once you can test it.

Have a great day, T.K.

snow-xf commented 1 week ago

Thank you for the update. I will keep an eye on the patch-4.0.0 branch, and I’ll proceed with testing once it’s ready on Saturday. Have a great day, too, T.K.!

FulcrumOne commented 1 week ago

Hey @snow-xf,

The problem should be fixed in the patch-4.0.0 branch - I would be very grateful if you could confirm this.

Have a great day, Tomasz

snow-xf commented 1 week ago

Hey Tomasz,  Thank you for the update. Unfortunately, the problem still persists in the patch-4.0.0 branch. Could we take another look at it?  “Error: updatePopupAction is nil”  Thanks for your efforts, and let me know if I can provide any additional information to help troubleshoot.  Best, Xuefei

FulcrumOne commented 1 week ago

Hey,

Sorry, my fault, I didn't look at your code properly.

Let's start by identifying the problem:

@main
struct TestApp: App {
    @StateObject var viewModel:TestViewModel = TestViewModel()
    var body: some Scene {
        WindowGroup {
            ContentView()
                .registerPopups()
                .environmentObject(viewModel)
        }
    }
}

The crash is caused by the ViewModel that you declared in the @main file. Why is this a problem? Because any change made to this ViewModel forces the application to re-create all the views in the WindowGroup (including those created by our library, unfortunately).

The solution I recommend is to move @StateObject from the @main structure to ContentView, so the final version of the code you provided would look like this:

import SwiftUI
import MijickPopups

@main
struct TestApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .registerPopups()
        }
    }
}

class TestViewModel:ObservableObject{
    @Published var text: String = ""
}

struct ContentView: View {
    @StateObject var viewModel:TestViewModel = TestViewModel()

    var body: some View {
        NavigationStack{
            List{
                NavigationLink {
                    NextView().environmentObject(viewModel)
                } label: {
                    Text("Next")
                }
            }
        }
    }
}

struct NextView:View {
    @EnvironmentObject var viewModel:TestViewModel
    @FocusState private var isInputFocused:Bool
    var body: some View{
        List{
            /// When editing the TextField, a Popup error occurs: "Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value"
            TextField("Edit Text", text: $viewModel.text,onCommit: {
                isInputFocused = false
            })
            .focused($isInputFocused)

            Button {
                isInputFocused = false
                Task { await TestBottomPopup().present() }
            } label: {
                Text("Test Popup")
            }
        }
    }
}

struct TestBottomPopup: BottomPopup {
    var body: some View{
        Text("Test")
            .padding()
            .onTapGesture {
                Task { await dismissLastPopup() }
            }
    }
    func configurePopup(config: BottomPopupConfig) -> BottomPopupConfig {
        config.tapOutsideToDismissPopup(true)
    }
}

And here is confirmation that it now works as expected: https://github.com/user-attachments/assets/9e5ec844-2e62-48ed-b84f-dcfd6474e003

Let me know if you have any further questions and have a nice day, Tomasz

sethi-ishmeet commented 1 week ago

I am having the same issue and honestly this solution is not gonna work for me. I should not have to change how my app (albeit incorrect) works fundamentally to use a library. For this reason only, I will skip using this otherwise awesome library.

FulcrumOne commented 1 week ago

@sethi-ishmeet,

Ok, there is another solution, which I strongly discourage as I haven't tested its impact on performance, BUT:

There are four attributes in the PopupView file on lines 19-22; if you declare all of them as @StateObject the problem with the crash will disappear, however, as I said, use it with caution.

Change from:

CleanShot 2024-11-17 at 01 54 47

To:

CleanShot 2024-11-17 at 01 54 58

snow-xf commented 1 week ago

Hi Tomasz, the issue has been resolved. Thank you!

sethi-ishmeet commented 1 week ago

@snow-xf what worked for you?

snow-xf commented 1 week ago

@snow-xf what worked for you?

https://github.com/Mijick/Popups/issues/158#issuecomment-2479067819