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

22

在我的应用程序中,已经自动创建了一个“关于我的应用程序”的菜单项,该菜单项将显示一个关于窗口。我该如何编辑此窗口?我想在那里添加一些额外的内容,但我找不到这个xib文件。

谢谢!


使用NSMenu和NSMenuItem添加项目。要编辑默认选项,请打开xib并编辑MainMenu。 - Parag Bafna
@Parag - 我想要编辑实际的关于窗口,而不是主菜单的菜单项。 - simon.d
2个回答

37

修改位于项目的“支持文件”组中的Credits.rtf文件内容。

输入映像说明


1
如果我想添加一些动态文本怎么办?例如,我想显示应用程序当前是否已经授权。这不是我可以放在Credits.rtf文件中的内容。 - simon.d
4
制作自己的窗口控制器并修改“关于我的应用程序”菜单按钮的目标和操作。然后,如果它被点击了,创建你的窗口控制器并显示其窗口。这样你就可以拥有一个自定义的.xib文件用于窗口(甚至可以通过编程方式加载)。@simon.d - 11684
如果我离开Credits.rtf,窗口会显示“[App Name] \n [Version number] ([Build number]) \n [Copyright]”。但是对于Safari来说,它是“[App Name] \n 版本 [Version number] ([Build number]) \n [Copyright]”。我该如何在版本号之前添加字符串“版本”? - Nicolas Miari
3
如果 Credits.rtf 不存在,则创建它,然后它会出现在关于对话框中。 - Borzh
1
我根据@11684的建议(自定义窗口控制器,从plist读取所有数据,使用NSApp中的图标图像)制作了一个演示项目:https://github.com/nicolas-miari/Cocoa-Custom-About-Window - Nicolas Miari
显示剩余6条评论

18
自动创建了一个名为“关于MyApp”的菜单项,并显示一个关于窗口,这是Cocoa应用程序的Xcode模板的标准功能。继续阅读以了解其如何连接。
要编辑此窗口该怎么做?我想在那里添加一些额外的内容,但我找不到xib文件。
没有xib文件:当应用程序对象([NSApplication sharedApplication])收到选中时发送的消息orderFrontStandardAboutPanelWithOptions:时,在运行时创建此窗口(如接口构建器中的连接检查器中可以验证)。默认情况下(正如其他人已经提到的),如果您的应用程序包资源中存在名为"Credits.rtf"的文件,则从该文件加载要显示的内容;否则,它会从您的应用程序的Info.plist条目中获取基本信息:
- 应用程序名称 - 绑定版本 - 版权声明
您可以按照以下方式覆盖此行为:
1. 在Interface Builder中创建一个自定义的“关于”窗口,具有您想要的所有子视图和标签。将文件命名为“AboutWindow.xib”。 2. 创建一个自定义的NSWindowController子类,用自定义窗口的nib名称初始化并设置为nib的所有者:
- (instancetype) init {
    if(self = [super initWithWindowNibName:@"AboutWindow" owner:self]){
        // (other initialization...)
    }

    return self;
}
  • 将 About 窗口的子视图连接到窗口控制器类中的 outlet。同时,将 File Owner 的类指定为自定义的 NSWindowController 子类,并将窗口的“New Referencing Outlet”连接到 File Owner 的 window 属性。

  • 在 Interface Builder 中打开 MainMenu.xib。删除与菜单项“关于…”相连接的操作,并将其重新连接到占位符对象“First Responder”的about:方法。
  • 在你的应用委托中,添加一个实例变量来保存你的窗口控制器,这样它不会立即被释放(或者将窗口控制器类设计成单例并使用共享实例):

  • @implementation AppDelegate {
    
        AboutWindowController *_aboutwindowController;
    }
    
  • 仍然在AppDelegate中,实现步骤3中已连接的about:方法,如下所示:

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

    ...或者,如果您的视图控制器实现为单例,像这样:

    - (IBAction)about:(id)sender {
        [[AboutWindowController defaultController].window orderFront:self];
    }
    
  • 最后,为了让您的窗口控制器能够正确地显示应用程序的信息,请从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"];
    }
    

    你可能会想从捆绑的资源中读取应用程序图标,但有一种更优雅的方法,即使您没有指定图标并且被困在默认的“尺子+铅笔+刷子覆盖的纸张”应用程序图标中也可以使用:使用以下代码获取运行时图标图像:

    self.appIconImageView.image = [NSApp applicationIconImage];
    

    我在Github上制作了一个演示项目,展示了自定义关于窗口的功能和其他自定义选项。点击此处查看。


    更新: 我已经在Github存储库中添加了一个Swift版本演示项目

    它具有以下功能:

    • Swift 4(现在Xcode 9是官方版本)
    • 使用Storyboard而不是xib
    • 将所有插座移动到新的视图控制器中,保留窗口外观代码在窗口控制器中。

    它是用Objective-C编写的;只要你的项目有桥接头文件,它应该与任何版本的Swift兼容。我会在某个时候制作一个Swift版本(目前还没有具体计划)。 - Nicolas Miari
    好的,你做完后给我打个标签!谢谢! - Dylan
    @dylan 抱歉回复晚了(但我希望你已经解决了)。你需要将菜单项的操作钩子连接到 First Responder 的 about: 方法。为了使其工作,该方法需要在 Swift 中具有 @IBOutlet func about(_ sender: Any) 的签名 (不要忘记参数名称前面的下划线!) - Nicolas Miari
    非常完整的答案。不过有一个问题 - 为什么不在您的AppDelegate中实现原始的“orderFrontStandardAboutPanelWithOptions:”来打开那个窗口?为什么需要“about:”操作? - Motti Shneor
    @MottiShneor 我不知道那个方法。 - Nicolas Miari
    显示剩余2条评论

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接