Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dismissAfter not dismissing on iOS13 #6

Closed
2 tasks done
LucasCarioca opened this issue Aug 15, 2020 · 17 comments
Closed
2 tasks done

dismissAfter not dismissing on iOS13 #6

LucasCarioca opened this issue Aug 15, 2020 · 17 comments
Labels
bug Something isn't working

Comments

@LucasCarioca
Copy link
Contributor

Pre-requisites:

  • Yes, I looked through both open and closed issues looking for what I needed
  • No, I did not find what I was looking for

I am trying to switch from my basic alerts to using ToastUI but I'm running into an issue. For some reason my toast won't dismiss even after the set dismissAfter time. Funny enough this is only an issue when running on a device with iOS <14. Seems like the dismissAfter functionality only works with the beta.

Expected Behavior

Should dismiss after the pre-defined time.

Current Behavior

Toast stays on the screen and dismiss is never called.

Possible Solution

Steps to Reproduce (for bugs)

    @State var showWarning = false // this is set to true when a warning is triggered
    var body: some View {
        VStack {
             ...
        }.toast(isPresented: $showWarning, dismissAfter: 5.0, onDismiss: {
            print("Dismissing") // this never prints and the toast never goes away.
        }) {
            ToastView(self.messageContent).toastViewStyle(WarningToastViewStyle())
        }
    }

Context

Your Environment

  • Swift Version: 5.3 & 5.1
  • Xcode Version: 12.0 Beta 4 & 11.4
  • Operating System and Version: macOS Big Sur 11 and macOS Catalina 10.15
  • Device or Simulator: Device - iPhone 7 Plus iOS 13.6.1
@quanshousio
Copy link
Owner

Although I couldn't exactly reproduce your bug on iOS 13.6, I came across another bug that also related to dismissing toast. I'm currently investigating and will push a fix later. Thanks for your report.

For temporary workaround, you can try using toast() without ToastView or view that uses cocoaBlur().

@quanshousio quanshousio added the bug Something isn't working label Aug 16, 2020
@LucasCarioca
Copy link
Contributor Author

LucasCarioca commented Aug 16, 2020

I did some debugging locally with the ToastUI code and isolated the issue to this:

    let keyWindow = UIApplication.shared.windows.first { $0.isKeyWindow }
    var rootViewController = keyWindow?.rootViewController
    ...
    let toastAlreadyPresented = rootViewController is ToastViewHostingController<QTContent>

It never evaluated to true when running on my iOS 13 device but does as expected on iOS 14 Simulator and Device.

@LucasCarioca
Copy link
Contributor Author

I also tried adding the dismiss here and it does dismiss the toast but the app crashes right after.

        if let dismissAfter = dismissAfter {
          DispatchQueue.main.asyncAfter(deadline: .now() + dismissAfter) {
            self.isPresented = false
          }
        }

@LucasCarioca
Copy link
Contributor Author

I also tried without the ToastView like you suggested and its the same issue. The root cause is in the modifier so that's called with or without the view. I could roll my own modifier for it which I may do just to get this out but I was trying to see if I could help resolve this.

@LucasCarioca
Copy link
Contributor Author

Actually some more digging and Its caused by the .onPreferenceChange(...) not kicking off when the isPresented value changes.

ToastViewModifier.swift: ToastViewIsPresentedModifier: body

internal func body(content: Content) -> some View {
    content
      .preference(key: ToastViewPreferenceKey.self, value: isPresented)
      .onPreferenceChange(ToastViewPreferenceKey.self) {
        self.present($0)
      }
  }

@quanshousio
Copy link
Owner

quanshousio commented Aug 16, 2020

It never evaluated to true when running on my iOS 13 device but does as expected on iOS 14 Simulator and Device.

Can you set a breakpoint at that expression after the toast is showing and po rootViewController? The debugger should outputs something like this:

(lldb) po rootViewController
▿ Optional<UIViewController>
  ▿ some : <_TtGC7SwiftUI19UIHostingControllerV17ToastUISample_iOS11ContentView_: 0x7fef5e511970>

That expression simply checks if the topmost view controller is currently our UIHostingController showing the toast or not, and it should evaluates to true in that case.

I also tried adding the dismiss here and it does dismiss the toast but the app crashes right after.

I'm not understand what you meant here as it's identical to what we're having right now

if let dismissAfter = dismissAfter {
DispatchQueue.main.asyncAfter(deadline: .now() + dismissAfter) {
self.isPresented = false
}
}

I also tried without the ToastView like you suggested and its the same issue. The root cause is in the modifier so that's called with or without the view. I could roll my own modifier for it which I may do just to get this out but I was trying to see if I could help resolve this.

Thank you for your information. I'm still trying to figure out what's the culprit here. It seems the app crashes right away when the toast dismisses due to the invalid usage of animating the blurred effect. I just pushed a fix on hotfix-1.0.2 branch, can you check that out to see if it works?

Actually some more digging and Its caused by the .onPreferenceChange(...) not kicking off when the isPresented value changes.

If that so, I'm doubting that this might be a SwiftUI bug. However, it's irritating that the bug happens on your device/simulator but not mine. Does your view belong to a bigger view hierarchy, or it just a simple VStack like you gave in the first example?

Thank you so much for taking your time, I really appreciate it. Hopefully we can get this fixed as quickly as possible.

@LucasCarioca
Copy link
Contributor Author

LucasCarioca commented Aug 16, 2020

Yeah the view itself is just a simple VStack it is being shown by a parent NavigationView (app drawer). To rule out any possible conflict there I also tried starting the app with that simple view as the main content view of the app and it still happens.

Just to clarify I have tried this in the following ways:

✅ = it worked
❌ = it didn't work

  • ✅ macOS 11 Big Sur with Xcode 12 beta 4 running on iPhone 11 Pro Max with iOS14 (Simulator)
  • ✅ macOS 11 Big Sur with Xcode 12 beta 4 running on iPhone X with iOS14 (Physical Device)
  • ❌ macOS 11 Big Sur with Xcode 12 beta 4 running on iPhone 7 Plus with iOS13 (Physical Device)
  • ❌ macOS 10.15 Catalina with Xcode 11.4 running on iPhone 7 Plus with iOS13 (Physical Device)
  • ✅ macOS 10.15 Catalina with Xcode 11.4 running on iPhone X with iOS14 (Physical Device)

The only common thing I can tell is iOS13 vs iOS14.

@LucasCarioca
Copy link
Contributor Author

Probably not as intended but I did get it to work using your hotfix branch. I pulled it down and made one small change and now it works. I think this kind of breaks other functionality you have though.

        if let dismissAfter = dismissAfter {
          DispatchQueue.main.asyncAfter(deadline: .now() + dismissAfter) {
            self.isPresented = false
            rootViewController?.dismiss(animated: true) // <-----ADDED THIS
          }
        }

@LucasCarioca
Copy link
Contributor Author

LucasCarioca commented Aug 16, 2020

Also without changing your code I got it working with the following:

.toast(isPresented: $showWarning) {
            ToastView{
                VStack {
                    ...
                    Button(action: {
                        self.showWarning = false
                        let keyWindow = UIApplication.shared.windows.first { $0.isKeyWindow }
                        let rootViewController = keyWindow?.rootViewController
                        rootViewController?.dismiss(animated: true)
                    }) {
                        Text("OK")
                    }
                }
            }
        }

@quanshousio
Copy link
Owner

Unfortunately, I still couldn't reproduce the bug. I currently don't have macOS 11.0 installed but I've tried all the following environments on latest macOS 10.15.6:

  • Xcode 11.4/11.6/12.0b4 with iPhone 8 Plus (Physical Device) running iOS 13.6
  • Xcode 11.4 with iPhone 11 Pro (Simulator) running iOS 13.4
  • Xcode 11.6 with iPhone 11 Pro (Simulator) running iOS 13.6
  • Xcode 12.0b4 with iPhone 11 Pro (Simulator) running iOS 14.0

@LucasCarioca
Copy link
Contributor Author

IOS13.6.1. Its very strange that its only happening that device. I’ll get ahold of another device to test on and make sure its not something strange with that.

If you want go ahead and lets consider that hotfix a resolution to this issue since it gives me at least a workaround. As long as it gets merged. I’ll look a little further into it on my end and if I can come up with a better way recreating it I’ll open a new issues with more information.

Thanks for taking the time to look into this!

@quanshousio
Copy link
Owner

No problem. Sorry for a little slow response as I'm still trying to figure out all the possible ways to reproduce this. By the way, have you tried cleaning the build folder, build from scratch and reinstall the application?

@LucasCarioca
Copy link
Contributor Author

I’ll give that a shot but no need to keep this open. I would just close this when that hotfix is merged.

Also no worries on response, you have actually been responding very quickly! 👍

@quanshousio
Copy link
Owner

I just merged hotfix-1.0.2 into master. Keep me update as I want this issue to be completely resolved.

@LucasCarioca
Copy link
Contributor Author

Closed in e0d402f

@LucasCarioca
Copy link
Contributor Author

@quanshousio fyi, I have not found out what the problem was yet but it has nothing to do with your code. I must be doing something strange with my views and not realizing it. I used the toast in a different location and it works fine out of the box. Just thought you should know.

Also I love this project thanks for putting it together.

@quanshousio
Copy link
Owner

quanshousio commented Aug 19, 2020

I'm glad it's working now, though I still feel weird that SwiftUI fails to call .onPreferenceChange() in some circumstances. Thank you so much for your support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants