Closed ajay-simform closed 1 year ago
This is an iOS bug with modals unrelated to SwiftMessages. I discovered the same issue a couple of months ago and filed a ticket with Apple.
What is happening is that the tap gesture is being shifted up. Try tapping a little bit below the button and you'll see that it is still tappable.
To demonstrate, the issue can be reproduced with this trivial SwiftUI view:
struct ContentView: View {
@State var isPresented = false
var body: some View {
VStack {
Button("Hello") { isPresented = true }
ScrollView {
}
}
.sheet(isPresented: $isPresented) {
Text("World")
}
}
}
Same problem. Tapping "Hello" doesn't work. Tapping below "Hello" works. Here's the sample project.
I do have a workaround though. I'm hesitant to put this into SwiftMessages because I'm not sure how robust it is. I can say that it is being used in a large scale app and there haven't been any issues.
The idea of the workaround is to mess with the key window after the modal is dismissed. To do this, I added this .onDismiss
modifier to presentedView
:
struct presentedView: View {
var body: some View {
...
.onDisappear {
// UIWindow.keyWindow is a custom property we use
guard let keyWindow = UIWindow.keyWindow else { return }
let window = UIWindow()
let vc = UIViewController()
window.rootViewController = vc
vc.loadViewIfNeeded()
vc.view.backgroundColor = .clear
window.windowScene = keyWindow.windowScene
window.makeKeyAndVisible()
keyWindow.makeKeyAndVisible()
}
}
}
extension UIWindow {
static var keyWindow: UIWindow? {
return UIApplication.shared.connectedScenes
.sorted { $0.activationState.sortPriority < $1.activationState.sortPriority }
.compactMap { $0 as? UIWindowScene }
.compactMap { $0.windows.first { $0.isKeyWindow } }
.first
}
}
private extension UIScene.ActivationState {
var sortPriority: Int {
switch self {
case .foregroundActive: return 1
case .foregroundInactive: return 2
case .background: return 3
case .unattached: return 4
@unknown default: return 5
}
}
}
The keyWindow
extension property was copied from SwiftMessages. What the workaround does is to quickly add and remove a transparent window after the modal is dismissed. There is no visible effect, but the process somehow fixes the corrupted tap handling.
Here's your sample project with the workaround applied:
Closing. Reopen if you need further help.
SwiftMessages
withpresentationContext = .window(windowLevel: UIWindow.Level.statusBar)
https://user-images.githubusercontent.com/47667077/203799756-578c4fa7-83b0-4708-9270-3d81807ba0bd.MP4
SwiftMessageDemo.zip