Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Senor Cuete

macrumors 6502
Original poster
Nov 9, 2011
448
32
I am working on a Mac application that was developed in Objective C and Interface builder. In earlier versions of MacOS the title of a window was centered. Now it's left-justified. Is there any way to center it? I can't see a setting for this in Interface builder. Reading the developer documentation, I can't can't see how to do this programmatically. Is this possible?
 
I’m away from my Mac right now so can’t investigate further but I am guessing you’re on macOS Tahoe and working in Xcode 26, building against the Tahoe sdk. I believe you will get a center justified title if you build against an older sdk. Left justification is part of the new default look and feel in Tahoe
 
Yes, Tahoe and XCode 26. Generally you have a lot of power to customize the appearance of your GUI, but maybe not in this case. Tahoe is butt ugly - a real disappointment.
 
It's a change in the behaviour of default title views. You can always make a Toolbar/Titlebar with custom views instead of you prefer, but in Tahoe the default for window titles is to be left aligned
 
I looked into this some more. This is cast in stone in Tahoe. In order to use special characters or justification in your window title you have to create a Title bar. This seems like a lot of hassle to work around inflexible requirements to use the latest cartoonish GUI.
 
I looked into this some more. This is cast in stone in Tahoe. In order to use special characters or justification in your window title you have to create a Title bar. This seems like a lot of hassle to work around inflexible requirements to use the latest cartoonish GUI.
I don't know, mate. The flexibility is there to do custom views, but the easy components are consistent with the system UI. That makes sense
 
According to the developer documentation you should create an NSTitlebarAccessoryViewController and then set the layoutAttribute property to:

The default value of this property is NSLayoutAttributeBottom, which means that the accessory view should display below the title bar. You can also set this property to NSLayoutAttributeRight or (in apps linked on macOS 10.11 or later) NSLayoutAttributeLeft. All other values are invalid and will cause an assertion to be raised.

BELOW, LEFT or RIGHT of the title bar but NOT over it. So can you really replace it with a title that can be justified or display special characters? According to the documentation you might be able to set the titleVisibility to windowTitleHidden and then set the layoutAttribute to NSLayoutAttributeRight. Has anyone actually done this?
 
Last edited:
According to the developer documentation you should create an NSTitlebarAccessoryViewController and then set the layoutAttribute property to:

The default value of this property is NSLayoutAttributeBottom, which means that the accessory view should display below the title bar. You can also set this property to NSLayoutAttributeRight or (in apps linked on macOS 10.11 or later) NSLayoutAttributeLeft. All other values are invalid and will cause an assertion to be raised.

BELOW, LEFT or RIGHT of the title bar but NOT over it. So can you really replace it with a title that can be justified or display special characters? According to the documentation you might be able to set the titleVisibility to windowTitleHidden and then set the layoutAttribute to NSLayoutAttributeRight. Has anyone actually done this?
Yes, you can hide the title with setTitleVisibility: NSWindowTitleHidden.

Now I'll create a title bar Accessory view. More news soon...
 
The easy way to add a custom title bar would be to create an xib, add an NSToolBar and link to it as an IBOutlet. The developer documentation says that an NSToolBar is: "An object that manages the space above your app’s custom content and either below or integrated with the window’s title bar." After struggling for a long time with the documentation I can't find a method to set the location to either above or below the title bar. Also there's no option to do this in Interface builder... The Sample Code "Integrating a Touch Bar and Tool Bar into your App" (in Swift only) doesn't describe how to do this either.

I guess I'll have to use an NSTitlebarAccessoryViewController instead because it does have a method to do this.

You can really get your mind twisted by trying to read Apple's developer documentation...
 
I was able to create my own title bar. I created a custom view with an NSSTextField in the object’s .xib, but not in the window’s hierarchy.

In the object’s implementation I declared two IBOutlets:
IBOutlet NSView *TitleBarView;
IBOutlet NSTextField *titleBarText;

In the object’s windowControllerDidLoadNib method I:
[objectsWindow setTitleVisibility: NSWindowTitleHidden]; //hides the default title
myTitleBar = [[NSTitlebarAccessoryViewController alloc] init];
[myTitleBar setLayoutAttribute: NSLayoutAttributeLeft];//draws it in the title bar next to the dots
[myTitleBar setView: TitleBarView];
[[theWindowController window] addTitlebarAccessoryViewController: myTitleBar];

The custom view has to be carefully sized to the default size of the window title bar.

You can set the justification of the text with the settings in Interface builder.

you can easily set the text in the title bar by calling [titleBarText setStringValue: NSString*];

You can’t set the NSTextField to an NSAttributedString, so if you want it to be a string with special characters, formatting, etc. you would have to set the graphics port to the custom view, move to x, y and draw the attributed string.
 
NSTextField has a `labelWithAttributedString:` method, so to set an attributed string you should be able to just use a label that allows rich text.
 
NSTextField has a `labelWithAttributedString:` method, so to set an attributed string you should be able to just use a label that allows rich text.
This is not a great way to do this because this is a class method that creates a new NSTextField with the attributed string. I already have an NSTextField that is instantiated when the .xib is loaded. It's sized to fit the TitleBarView, controlled by the NSTitlebarAccessoryViewController and it's justification is centered. I suppose you could set the NSTextField pointer to the new text field and release or dealloc the old one but you would have to set all of the text field and attributed string attributes each time you do this. I can't see an easy way to set a text field's content to an attributed string or an object from IB's library to do this.
 
I only mentioned it to show that it is possible to create a NSTextField that can use attributed strings. Personally, I just use a method with various optional parameters to create attributed strings, and include it in projects where I want to use them. Then again, I don't use Interface Builder, so I suppose it might be a bit of an overkill if you do.
 
Thanks so much for your help. I also want the window title to remain centered when I narrow the window. I thought that this could be done with layout constraints but it doesn't want to work in a title bar.
 
Views can be configured to auto-resize their sub-views but not windows. The title bar isn't in the window's view so it can't be configured with layout constraints to change when you narrow the window.
 
It turns out that you can set an NSTextField to an atttributed string using the method setAttributedStringValue: This is interesting because when I look at NSTextField in the developer documentation neither the stringValue or attributedStringValue properties (methods) are listed. I'll look at this more.
 
When I narrowed the window with the width scrollbar the justified title would not also move to the left. To cause the window title to stay centered in the window title I added the following code to the overridden class method -(void) userResizedWindow: (NSNotification *) note method.
You can get the window pointer like this: NSWindow *myWindow = [note object]; Then I use the following code:
Code:
NSView *myWindowview = [myWindow contentView];
NSRect myFrame = [myWindowview frame];
CGFloat windowWidth = myFrame.size.width;
NSView *mySuperview = [[myTitleBar view] superview];
myFrame = [mySuperview frame];
CGFloat leftOffset = myFrame.origin.x;
CGFloat titleBarWidth = windowWidth - leftOffset;
myFrame.size.width = titleBarWidth;
[TitleBarView setFrame: myFrame];
The window title is centered in its text field, so it stays in the center of the window's title bar whenever you resize the width of the window with its scroll bar.
 
Last edited:
The run time won't crash but it will complain: not allowed to set frame origin, so you should replace the lines
Code:
myFrame.size.width = titleBarWidth;
TitleBarView setFrame: myFrame];
with:
Code:
myFrame = [TitleBarView frame];
myFrame.size.width = titleBarWidth;
[TitleBarView setFrame: myFrame];
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.