UINavigationItem.titleView layout issue

Adapter subviews of the titleView have wrong frames. I would open a bug - it feels like no one looking at them, at least none of my previous bugs were addresses... so it feels pointless. Hope this helps someone facing similar issues.

Answered by Frameworks Engineer in 724321022

What are you trying to resolve? In general if your getting a _UITAMICAdaptorView its because UIKit is putting you on a compatibility path. In almost every case, using auto layout will produce significantly better results.

The simplest case is if your custom title view already provides sizing information. If it were using auto layout internally it is likely that we wouldn't have created a _UITAMICAdaptorView in the first place, so I assume you aren't. If you are overriding intrinsicContentSize then setting translatesAutoresizingMaskIntoConstraints=true before you pass us the title view should ensure that we query that. If you aren't doing that, just adding two constraints based on widthAnchor and heightAnchor is a very simple way to provide sizing information for a custom view (if you do this we recommend ensuring their priority is less than Required (aka 1000)).

But even if you make none of those changes, having your view override sizeThatFits: should ensure reasonable layout, alongside sizing the view to a reasonable size before you pass it to UIKit. But using autolayout will give you more flexibility and better behavior.

But please do file the bug you encountered, although it is very late in the beta cycle so it may be hard to get it fixed for iOS 16. In general the sooner you file bugs the better.

My solution is to get the bounds of the the self.superview.superview -> _UINavigationBarTitleControl, instead of relying on the bounds of the self.superview -> _UITAMICAdaptorView.

Accepted Answer

What are you trying to resolve? In general if your getting a _UITAMICAdaptorView its because UIKit is putting you on a compatibility path. In almost every case, using auto layout will produce significantly better results.

The simplest case is if your custom title view already provides sizing information. If it were using auto layout internally it is likely that we wouldn't have created a _UITAMICAdaptorView in the first place, so I assume you aren't. If you are overriding intrinsicContentSize then setting translatesAutoresizingMaskIntoConstraints=true before you pass us the title view should ensure that we query that. If you aren't doing that, just adding two constraints based on widthAnchor and heightAnchor is a very simple way to provide sizing information for a custom view (if you do this we recommend ensuring their priority is less than Required (aka 1000)).

But even if you make none of those changes, having your view override sizeThatFits: should ensure reasonable layout, alongside sizing the view to a reasonable size before you pass it to UIKit. But using autolayout will give you more flexibility and better behavior.

But please do file the bug you encountered, although it is very late in the beta cycle so it may be hard to get it fixed for iOS 16. In general the sooner you file bugs the better.

It helps me to solve this issue

    let navBarTitleView = UIImageView(image: UIImage(named: "topLogo"))
    navBarTitleView.contentMode = .center
    navBarTitleView.translatesAutoresizingMaskIntoConstraints = false
    if let navigationBarHeight = navigationController?.navigationBar.bounds.height {
      navBarTitleView.heightAnchor.constraint(equalToConstant: navigationBarHeight).isActive = true
    }
    navBarTitleView.widthAnchor.constraint(equalToConstant: navBarTitleView.bounds.width).isActive = true
    navigationItem.titleView = navBarTitleView

After updating to IOS 16 I see my custom title view is getting placed in the wrong position on the y axis.

My app conditions are this: -My custom title view isn't shown all the time (dynamically added/removed).
-When the custom title view is first set it is placed approximately at the center of the navigation bar on both the x and y axis as expected. -After certain events happen my app sets the custom title view to nil to remove it. -When I reset the custom title view, it gets placed either at the top or the bottom of the navigation bar on the y axis instead of the center.

This custom title view has a static frame, so I tried caching the size and returning it in -intrinsicContentSize but the system never calls intrinsicContentSize even though translatesAutoresizingMaskIntoConstraints is YES.

So I tried overriding -sizeThatFits: and that is actually called by the system but the issue persists because the size of the custom title view's frame is fine it's the origin that is wrong. So I logged out the frames of my custom title view its ancestor views like this:

 NSLog(@"My frame: %@",NSStringFromCGRect(frame));
NSLog(@"superview %@ frame: %@",NSStringFromClass([superview class]),NSStringFromCGRect(superview.frame));
NSLog(@"superview.superview %@ frame: %@",NSStringFromClass([superview.superview class]),NSStringFromCGRect(superview.superview.frame));

When the custom title view is approx placed in the right location the first time its set the frames log out to this:

My frame: {{0, 0}, {161.5, 23}}

superview _UITAMICAdaptorView frame: {{0, 0}, {161.5, 23}}

superview.superview _UINavigationBarTitleControl frame: {{291.5, 3}, {161.5, 23}}

Then when it later gets reset and it is not properly placed on the y axis:

My frame: {{0, 0}, {161.5, 23}}

superview _UITAMICAdaptorView frame: {{0, 0}, {161.5, 23}}

superview.superview _UINavigationBarTitleControl frame: {{291.5, 24}, {161.5, 23}}


For some reason when the titleView is set the second time _UINavigationBarTitleControl yOrigin is 24.0. Initially it has a y origin of 3.0 when the custom title view appears to be in the correct location.

I tried setting auto layout constraints, which did in fact cause _UITAMICAdaptorView to be removed from the view hierarchy but in my case that has nothing to do with the UI glitch (the custom view still appears at the wrong location on y axis because of _UINavigationBarTitleControl yOrigin)

I was able to reproduce it in a small sample project after awhile. The key to reproduce it is to make sure the navigationItem's title property is set. Have the title property set to a non nil value and also set the titleView. Then if "Debug View Hierarchy" I can see that _UINavigationBarTitleControl has an ambiguous vertical position.

Anything I can do to workaround this issue?

Okay so setting the title to nil before setting the titleView works around the issue. However this may have side effects if you read the title from other areas in your code (as a generic reference to build alerts titles etc.)...seems like it should be okay to have .title and .titleView set (was the case before iOS 16 anyway).

UINavigationItem.titleView layout issue
 
 
Q