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

iOS 18 touch injection hit testing fix for SwiftUI view hierarchies #1323

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

BartlomiejWlodarczak
Copy link

This PR should fix the issue #1302

There were additional mechanisms provided by Apple for SwiftUI / UIKit gesture interoperability. They needed to implement it somehow, hence the presence of new structures SwiftUI.UIKitGestureContainer and _UIHitTestContext. I tried to mimic what's actually going on during "real" touches on iOS 18.

I had also needed to bump the deployment target to iOS 13, since I was planning on adding a basic SwiftUI testing screen to the tests host app.

@justinseanmartin
The UIWebView related logic can be ditched fully in favor of WKWebView if you decide to merge this PR.
I made adjustments for the rest of deprecation warnings.

Package.swift Show resolved Hide resolved
Copy link

@lolindrath lolindrath left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking really good! I ran our tests and almost all of them passed. clearTextFromView is still failing - do you think that's related to this issue? The error I see is:

with label "Label name" is not tappable. It may be blocked by other views.

@BartlomiejWlodarczak
Copy link
Author

@lolindrath I can't really tell as I don't know what is the view hierarchy and test's logic in that failing test you mentioned. Would you like to share some more details?

Meanwhile I verified that current implementations of tester methods for text manipulation are working with the SwiftUI TextField view. I also added related tests.

@justinseanmartin
Copy link
Contributor

Thank you very much for contributing this! Tagging in @congt who can also tag in some other two repo admins to help move this forward. I'm on sabbatical for a while and not actively doing work things. I'll give it a once over, but I no longer have access to run the Block internal test suite to make sure it doesn't have any other side effects.

Copy link
Contributor

@justinseanmartin justinseanmartin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, this looks like a really well done change. Thanks for taking the time and effort to add all the tests. It seems like it could alter the behavior even in UIKit views, is that right? It's fine as long as it doesn't break behavior there.

FYI - There is a note about the supported iOS versions in the README that looks like it needs updating. It's already stale though. I'd guess this change also warrants a minor version bump and release cut to signify the notable added support. It is probably worth mentioning the SwiftUI support in the README as well. All this probably can be handled by repo maintainers after merging this PR as part of cutting a release, but defer to @congt et al on that.

@@ -6,7 +6,7 @@ Pod::Spec.new do |s|
s.license = 'Apache 2.0'
s.authors = 'Michael Thole', 'Eric Firestone', 'Jim Puls', 'Brian Nickel'
s.source = { :git => "https://github.com/kif-framework/KIF.git", :tag => "v#{ s.version.to_s }" }
s.platform = :ios, '11.0'
s.platform = :ios, '13.0'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely seems reasonable to bump this IMO.

- (float)animationSpeed
{
if (!self.keyWindow) {
UIWindow *keyWindow = [self windowSceneKeyWindow];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for doing the update here

Comment on lines +159 to +165
/*
From observation - this can be either of following types:
- UIView type (e.g. when using UIViewRepresentable inside SwiftUI)
- specialized SwiftUI view compatible with UIView,
- newly introduced structure SwiftUI.UIKitGestureContainer implementing UIResponder interface.
What's important it seems it is compatible with setView:(UIView *) method.
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great context, thank you for including this.

@BartlomiejWlodarczak
Copy link
Author

@justinseanmartin thank you for your feedback on this!

Answering your question - whether or not it alters the current behavior for UIKit views. When there are just UIKit views in the view hierarchy it'll iterate it trying to create the new hit test context structure, which won't happen as it is only created when SwiftUI or SwiftUI + UIKit views are involved in the hierarchy. So it'll end up returning same ol' hitTestView that was used until now.

When I initially started working on this last year I tried to avoid that loop heuristically e.g. when the initially returned hitTestView was of a class containing keywords like SwiftUI / UIHostingView etc. but I found some SwiftUI views with really obfuscated names, so this wouldn't work and was failing in some situations.

So far after running the entire test suite before and after those changes I feel that the performance impact is negligible.

@justinseanmartin
Copy link
Contributor

So far after running the entire test suite before and after those changes I feel that the performance impact is negligible.

@BartlomiejWlodarczak - I'm not worried about the perf impact either FWIW. KIF spends a lot of cycles walking the view hierarchy and I don't think that -[UITouch initAtPoint:inWindow:] gets called all that often by comparison.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants