Skip to content

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

Merged
congt merged 11 commits into
kif-framework:masterfrom
BartlomiejWlodarczak:swiftui-ios-18-touch-fix
Feb 18, 2025
Merged

iOS 18 touch injection hit testing fix for SwiftUI view hierarchies#1323
congt merged 11 commits into
kif-framework:masterfrom
BartlomiejWlodarczak:swiftui-ios-18-touch-fix

Conversation

@BartlomiejWlodarczak

Copy link
Copy Markdown
Contributor

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.

Comment thread Package.swift

@lolindrath lolindrath left a comment

Copy link
Copy Markdown

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
Copy Markdown
Contributor 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
Copy Markdown
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.

@justinseanmartin justinseanmartin left a comment

Copy link
Copy Markdown
Contributor

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.

Comment thread KIF.podspec
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
Contributor 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
Copy Markdown
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.

@bcriscuolo

Copy link
Copy Markdown

@justinseanmartin based on this work, what's the possibility of moving this into a formal KIF tagged release? We're eager to consume this and move to our functional automation on iOS 18 simulators.

Thanks!

@congt

congt commented Feb 18, 2025

Copy link
Copy Markdown
Contributor

@justinseanmartin based on this work, what's the possibility of moving this into a formal KIF tagged release? We're eager to consume this and move to our functional automation on iOS 18 simulators.

Thanks!

Sorry for the slow response. Looks like some tests are still broken. @BartlomiejWlodarczak Could you take a look?

@BartlomiejWlodarczak

Copy link
Copy Markdown
Contributor Author

@congt Sorted it out together with some build warnings from the logs.

@congt congt merged commit 259c5e6 into kif-framework:master Feb 18, 2025
@ispatel22

Copy link
Copy Markdown

@justinseanmartin @congt can you make a new release version with the merged changes?

@justinseanmartin

Copy link
Copy Markdown
Contributor

@ispatel22 - I'll coordinate with Cong to make sure a release gets cut. In the meantime, you should be able to point at revision 259c5e6.

@congt

congt commented Feb 19, 2025

Copy link
Copy Markdown
Contributor

Here is the PR to bump the version #1325

@congt

congt commented Feb 19, 2025

Copy link
Copy Markdown
Contributor

3.11.2 was just released

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.

7 participants