Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I modify the automatically generated About window in my Cocoa app?

A menu item for "About MyApp" was automatically created for me and it displays an about window. How do I edit this window? I'd like to add some extra stuff there but I can't find the xib anywhere.

Thanks!

like image 984
simon.d Avatar asked Dec 14 '11 06:12

simon.d


2 Answers

Modify the contents of Credits.rtf file located inside the 'supporting files' group of your project.

enter image description here

like image 199
Michael Robinson Avatar answered Oct 17 '22 06:10

Michael Robinson


A menu item for "About MyApp" was automatically created for me and it displays an about window.

This is standard with Xcode templates for Cocoa apps. Keep reading to see how it is wired.

How do I edit this window? I'd like to add some extra stuff there but I can't find the xib anywhere.

There is no xib: This window is created at runtime by the application object ([NSApplication sharedApplication]), when it receives the message orderFrontStandardAboutPanelWithOptions:, which that menu item sends when selected (as you an verify in the Connections Inspector in Interface Builder).

By default (as others have mentioned), it loads the contents to display from a file named "Credits.rtf" if such file exists within your app bundle's resources; otherwise it grabs basic info from your app's Info.plist entries:

  • App name
  • Bundle version
  • Copyright notice

What you can do is override this behaviour as follows:

  1. Create a custom "About" window in Interface builder, with all the subviews and labels you want. Name the file "AboutWindow.xib".
  2. Create a custom NSWindowController subclass, initialized with your custom window's nib name and set as the nib's owner:

    - (instancetype) init {
        if(self = [super initWithWindowNibName:@"AboutWindow" owner:self]){
            // (other initialization...)
        }
    
        return self;
    }
    
  3. Connect your About window's subviews to outlets in the window controller class. Also, specify the class for File Owner as your custom NSWindowController subclass and connect the window's "New Referencing Outlet" to File Owner's window property.

  4. Go to MainMenu.xib in Interface Builder. Remove the action that is wired to the menu item "About ...", and re-wire a new one to the about: method of the placeholder object "First Responder".
  5. In your app delegate, add an instance variable to hold your window controller so it does not get deallocated right away (alternatively, make your window controller class a singleton and use the shared instance):

    @implementation AppDelegate {
    
        AboutWindowController *_aboutwindowController;
    }
    
  6. Still in AppDelegate, implement the method about: that you wired in step 3, like this:

    - (IBAction)about:(id)sender {
        if (_aboutwindowController == nil) {
            _aboutwindowController = [AboutWindowController new];
        }
    
        [_aboutwindowController.window orderFront:self];
    }
    

    ...or, if your view controller is implemented as a singleton, like this:

    - (IBAction)about:(id)sender {
        [[AboutWindowController defaultController].window orderFront:self];
    }
    
  7. Finally, in order for your window controller to correctly display your app's information, read the relevant keys from the Info.plist file, like this (actual outlet ivars will be different in you case):

    - (void)windowDidLoad {
        [super windowDidLoad];
    
        // Implement this method to handle any initialization after your window
        // controller's window has been loaded from its nib file.
    
        NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
    
        self.appNameLabel.stringValue      = [infoDictionary objectForKey:@"CFBundleName"];    
        self.appVersionLabel.stringValue   = [infoDictionary objectForKey:@"CFBundleShortVersionString"];
        self.appCopyrightLabel.stringValue = [infoDictionary objectForKey:@"NSHumanReadableCopyright"];
    }
    

You might be tempted to read the app icon from the bundled resources too, but there's a more elegant way that works even if you didn't specify an icon and are stuck with the default "Ruler + Pencil + Brush over a Sheet" app icon: Grab the runtime icon image using the following code:

self.appIconImageView.image = [NSApp applicationIconImage];

I have put together a demo project on Github that shows this and further customizations of the About window.


UPDATE: I have added a Swift version of the demo project to the Github repository.

It features:

  • Swift 4 (now that Xcode 9 is official)
  • Storyboards instead of xibs
  • Moved all the outlets to the new view controller, kept window appearance code in the window controller.
like image 35
Nicolas Miari Avatar answered Oct 17 '22 05:10

Nicolas Miari