gpt4 book ai didi

cocoa - 如何在基于 NSDocument 的 Cocoa 应用程序中使用 NSViewController

转载 作者:行者123 更新时间:2023-12-03 16:07:01 26 4
gpt4 key购买 nike

我有丰富的 iOS 经验,但 Cocoa 让我有点困惑。我阅读了几个关于 Cocoa 的 Apple 文档,但仍然有一些细节我无法在任何地方找到。似乎文档是在基于 NSDocument 的 Xcode 模板更新为使用 NSViewController 之前编写的,因此我不清楚应该如何组织我的应用程序。该模板使用 NSWindow、NSViewController 创建 Storyboard。

我的理解是,我可能应该子类化 NSWindowController 或 NSWindow 以引用我的模型对象,并在 makeWindowControllers() 中设置它。但如果我想使用 NSViewController 而不是将所有内容都放在窗口中,我还需要以某种方式访问​​我的模型。我注意到我的 View Controller 中有一个叫做representedObject的东西,它看起来像是用来保存一些模型对象(然后被转换)的,但它总是为零。这是如何设置的?

我发现很难正确地提出这个问题,但我想我要问的是:如何在基于文档的应用程序中正确使用 NSViewController?

PS:我知道 NSWindowController 通常用于管理作用于一个文档的多个窗口,因此大概如果我只需要一个窗口,那么我就不需要 NSWindowController。但是,需求可能会发生变化,从长远来看,使用 NSWindowController 可能会更好,对吗?

最佳答案

我还没有深入研究 Storyboard,但它的工作原理如下:

如果您的应用必须支持 10.9 及更低版本,请创建 NSWindowController 子类的自定义

Document based app

将这样的代码放入 NSDocument 子类中

- (void)makeWindowControllers
{
CustomWindowController *controller = [[CustomWindowController alloc] init];
[self addWindowController:controller];
}

如果您的应用程序有多个窗口,请将它们添加到此处或其他位置(按需加载),但不要忘记将其添加到文档 windowscontroller 数组中(addWindowController:)

如果您创建它们但不想显示所有窗口,则覆盖

- (void)showWindows
{
[controller showWindow:nil]
}

您可以随时在窗口 Controller 中访问您的模型

- (CustomDocument *)document
{
return [self document];
}

在窗口 Controller 中使用绑定(bind)(窗口 Controller 子类+键路径中的文档,这是窗口 Controller 的属性)

[self.textView bind:@"editable"
toObject:self withKeyPath:@"document.readOnly"
options:@{NSValueTransformerNameBindingOption : NSNegateBooleanTransformerName}];

与 iOS 相比,大多数 View 都在屏幕上,因此您必须依赖模式:委派、通知、事件(响应程序链),当然还有 MVC。

10.10 优胜美地变化:

NSViewController 从 10.10 开始自动添加到响应者链(通常操作的目标未知 | NSApp sendAction:to:from:)iOS 中熟悉的 viewDidLoad... 等所有委托(delegate)终于实现了。这意味着我不再看到子类化 NSWindowCotroller 的巨大好处。

NSDocument 子类是必需的,NSViewController 就足够了。

您可以随时访问 View Controller 中的数据

- (CustomDocument *)document
{
return (CustomDocument *)[[NSDocumentController sharedDocumentController] documentForWindow:[[self view] window]];
//doesn't work if you do template approach
//NSWindowController *controller = [[[self view] window] windowController];
//CustomDocument *document = [controller document];
}

如果您这样做(符合 KVC/KVO),您可以按照上面的说明进行绑定(bind)。

提示:为文档中的模型对象正确实现 UNDO,例如或者可耻地调用 updateChangeCount:

[[self.undoManager prepareWithInvocationTarget:self] deleteRowsAtIndexes:insertedIndexes];

不要将与 View /窗口相关的代码放入文档中

将您的应用程序拆分为多个 NSViewController,例如

- (void)prepareForSegue:(NSStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:AAPLListWindowControllerShowAddItemViewControllerSegueIdentifier]) {
AAPLListViewController *listViewController = (AAPLListViewController *)self.window.contentViewController;

AAPLAddItemViewController *addItemViewController = segue.destinationController;

addItemViewController.delegate = listViewController;
}
}

以前的代码是在 windowcontroller 上调用的,viewcontroller 作为委托(delegate)(同样只有在 10.10 之后才可能)

我总是更喜欢使用多个 XIB,而不是一个巨大的 Storyboard/XIB。使用 NSViewController 的以下子类并始终继承它:

#import <Cocoa/Cocoa.h>

@interface MyViewController : NSViewController

@property(strong) IBOutlet NSView *viewToSubstitute;

@end

#import "MyViewController.h"

@interface MyViewController ()

@end

@implementation MyViewController

- (void)awakeFromNib
{
NSView *view = [self viewToSubstitute];
if (view) {
[self setViewToSubstitute:nil];
[[self view] setFrame:[view frame]];
[[self view] setAutoresizingMask:[view autoresizingMask]];
[[view superview] replaceSubview:view with:[self view]];

}
}

@end
  1. 使用 XIB 将 MyViewController 的子类添加到项目中。重命名 XIB
  2. 将 NSViewController 对象添加到 XIB 并更改其子类名称 Howto2
  3. 将加载的 XIB 名称更改为步骤 1 中的名称 Howto3
  4. 链接 View 以替换您要替换的 View Howto1检查示例项目Example Multi XIB project

通过 shapeart 激励自己或listerTextEdit

真正的指南是使用 Hopper并看看其他应用程序是如何完成的。

PS:您可以将您的 View / View Controller 添加到responder chain中手动。

PS2:如果您是初学者,请不要过度架构。对您的应用程序的运行感到满意。

关于cocoa - 如何在基于 NSDocument 的 Cocoa 应用程序中使用 NSViewController,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32316958/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com