如何在Cocoa应用程序中修改自动生成的"关于"窗口?

sim*_*n.d 20 macos xcode cocoa objective-c

自动为我创建了"关于MyApp"的菜单项,它显示了一个关于窗口的信息.如何编辑此窗口?我想在那里添加一些额外的东西,但我无法在任何地方找到xib.

谢谢!

Mic*_*son 33

修改Credits.rtf位于项目"支持文件"组内的文件内容.

在此输入图像描述

  • 制作自己的窗口控制器并修改"关于MyApp"菜单按钮的目标和操作.然后,如果单击它,则创建窗口控制器并显示其窗口.这样你就可以为窗口定制一个`.xib`文件(甚至可以以编程方式加载它).@ simon.d (4认同)
  • 如果Credits.rtf不存在,则创建它,它将显示在"关于"对话框中. (2认同)

Nic*_*ari 12

自动为我创建了"关于MyApp"的菜单项,它显示了一个关于窗口的信息.

这是Cocoa应用程序的Xcode模板的标准.继续阅读以了解它是如何连接的.

如何编辑此窗口?我想在那里添加一些额外的东西,但我无法在任何地方找到xib.

没有xib:这个窗口是在运行时由应用程序对象([NSApplication sharedApplication])在运行时创建的,当它收到消息时orderFrontStandardAboutPanelWithOptions:,该菜单项在被选中时发送(当你在Interface Builder的Connections Inspector中验证时).

默认情况下(正如其他人所提到的),如果此类文件存在于您的应用程序包的资源中,它会加载要从名为"Credits.rtf"的文件中显示的内容.否则它会从您应用的Info.plist条目中获取基本信息:

  • 应用名称
  • 捆绑版
  • 版权声明

您可以做的是覆盖此行为,如下所示:

  1. 在"界面"构建器中创建自定义"关于"窗口,其中包含所需的所有子视图和标签.将文件命名为"AboutWindow.xib".
  2. 创建一个自定义NSWindowController子类,使用自定义窗口的nib名称初始化并设置为nib的所有者:

    - (instancetype) init {
        if(self = [super initWithWindowNibName:@"AboutWindow" owner:self]){
            // (other initialization...)
        }
    
        return self;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 将About窗口的子视图连接到窗口控制器类中的出口.另外,将File Owner的类指定为自定义NSWindowController子类,并将窗口的"New Referencing Outlet"连接到File Owner的window属性.

  4. 转到Interface Builder中的MainMenu.xib.删除连接到菜单项"关于..."的操作,并将新的连接重新连接到about:占位符对象"First Responder"的方法.
  5. 在你的app delegate中,添加一个实例变量来保存你的窗口控制器,这样它就不会立即被释放(或者,让你的窗口控制器类成为单例并使用共享实例):

    @implementation AppDelegate {
    
        AboutWindowController *_aboutwindowController;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  6. 仍然在AppDelegate中,实现about:您在步骤3中连接的方法,如下所示:

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

    ...或者,如果您的视图控制器实现为单例,如下所示:

    - (IBAction)about:(id)sender {
        [[AboutWindowController defaultController].window orderFront:self];
    }
    
    Run Code Online (Sandbox Code Playgroud)
  7. 最后,为了让您的窗口控制器正确显示您的应用程序的信息,请阅读Info.plist文件中的相关键,如下所示(实际的插座ivars在您的情况下会有所不同):

    - (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"];
    }
    
    Run Code Online (Sandbox Code Playgroud)

您可能也试图从捆绑的资源中读取应用程序图标,但即使您没有指定图标并且卡在默认的"标尺+铅笔+画笔在工作表上"应用程序图标,也会有更优雅的方式工作:使用以下代码获取运行时图标图像:

self.appIconImageView.image = [NSApp applicationIconImage];
Run Code Online (Sandbox Code Playgroud)

在Github上放了一个演示项目,显示了这个以及关于窗口的进一步自定义.


更新:我已经向Github存储库添加了Swift版本演示项目.

它的特点是:

  • Swift 4(现在Xcode 9正式版)
  • 故事板而不是xibs
  • 将所有插座移动到新视图控制器,将窗口外观代码保存在窗口控制器中.