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

Safe area insets are not respected when setting overrideUserInterfaceStyle on a MessageView in iOS 17 #532

Open
jmarr opened this issue Oct 19, 2023 · 3 comments
Labels

Comments

@jmarr
Copy link

jmarr commented Oct 19, 2023

In my app, I'm setting overrideUserInterfaceStyle on my MessageView to force a dark appearance when the app is in light mode.

However, when doing this on iOS 17, the MessageView no longer respects the safe area of the view controller it's being presented in. The MessageView is presented correctly on iOS 16.

I've attached a sample project that reproduces the issue. Run the sample project on a simulator or device running iOS 17 that has a bottom safe area inset. Tap the Show Message button and you'll see the message overlaps the safe area, as shown in the screenshot below. If you comment out the line that sets overrideUserInterfaceStyle or present the message while in dark mode, the message will correctly appear above the safe area.

Screenshot showing message overlapping safe area

In stepping through the code, it looks like after calling container.layoutIfNeeded() on line 100 of TopBottomAnimation.swift, the frame of container is changed and no longer overlapping the safe area, so the safe area isn't taken into account by the call to adjustMargins.

Looking at the constraints, I don't see why container would no longer be filling its parent view, but I did notice that after the call to layoutIfNeeded, container.hasAmbigousLayout() returns true. I highly suspect this is an iOS bug.

FWIW, I did discover that container lays out correctly if I call container.superview.layoutIfNeeded() instead of container.layoutIfNeeded(), so that might be a potential fix / workaround.

I don't understand why this only occurs when setting overrideUserInterfaceStyle, but there is a comment for overrideUserInterfaceStyle in UIView.h that says "Starting in iOS 17, this also affects any nested view controllers and subviews of those view controllers.", so Apple did make changes to the behavior of that property in iOS 17.

For my own app, I'm now configuring the MessageView with the appearance I want without using overrideInterfaceStyle, but I wanted to file an issue here so you can potentially look into it further and so anyone else seeing this behavior can learn how to work around it.

@wtmoose
Copy link
Member

wtmoose commented Oct 20, 2023

@jmarr I appreciate the detailed writeup. I'm unlikely to look at this anytime soon given that it is an obscure problem and you have a workaround. Hopefully it will resolve itself in a future version of iOS.

@jmarr
Copy link
Author

jmarr commented Oct 20, 2023

@wtmoose Thanks and yeah, that's totally understandable. I mostly wanted to post it here in case anyone else runs into the issue, since it took a while to discover thatoverrideUserInterfaceStyle was triggering it.

In our app the issue was much more noticeable because we have a container view with a bottom bar that sets additionalSafeAreaInsets on its children, so the message was appearing entirely behind the bar.

And yes, hopefully the underlying issue will be resolved in an iOS update, though I did verify it's still happening on the latest iOS 17.1 beta.

@wtmoose wtmoose added the bug label Oct 24, 2023
@jmarr
Copy link
Author

jmarr commented Oct 24, 2023

I just discovered that this issue also occurs when showing a message from a view controller that's being presented.

  1. Build and run this project on a device with safe areas.
  2. Tap Show Message and note that the message respects the safe area.
  3. Tap Present View Controller.
  4. Tap Show Message and note that the message overlaps the safe area.

The issue doesn't occur if I change the presentationContext from .viewController(self) to .window(windowLevel: .normal)

In stepping through the code, after calling container.layoutIfNeeded() on line 100 of TopBottomAnimation.swift, the frame of container is changed and no longer overlapping the safe area, so the safe area isn't taken into account by the call to adjustMargins, just like when overrideUserInterfaceStyle was used.

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

No branches or pull requests

2 participants