简体   繁体   English

基于文档的应用程序与情节提要板自动保存

[英]Document-Based App autosave with storyboards

In Document-Based Apps, using XIB files, when a new window is created its behaviour is: 在基于文档的应用程序中,使用XIB文件创建新窗口时,其行为是:

  1. Be positioned and sized based on the position of the last active window. 根据最后一个活动窗口的位置进行定位和调整大小。
  2. If the last active window is still visible then the new window should be cascaded so it doesn't directly overlap. 如果最后一个活动窗口仍然可见,则应级联新窗口,以使其不会直接重叠。

However when using a storyboard this isn't done. 但是,使用情节提要板时并不会这样做。 See test project . 请参阅测试项目

You can set shouldCascadeWindows on the window controller in your storyboard: 您可以在情节提要中的窗口控制器上设置shouldCascadeWindows:

  1. select the window controller in the storyboard 在情节提要中选择窗口控制器
  2. select the identity inspector 选择身份检查器
  3. add a new User Defined Runtime Attribute with these values: 使用以下值添加新的用户定义的运行时属性:
  • key path: shouldCascadeWindows 关键路径:shouldCascadeWindows
  • Type: boolean 类型:布尔值
  • Value: checked 值:选中

Update: If you move the first window, new windows cascade starting in the middle of the screen not under the first window. 更新:如果移动第一个窗口,则新窗口将从屏幕中间而不是第一个窗口开始级联。 To fix it: 要解决这个问题:

  1. select the window 选择窗口
  2. in the attributes inspector give it an autosave name 在属性检查器中为其指定一个自动保存的名称

This should also persist window location and size on the next window load and application launch. 在下一次加载窗口和应用程序启动时,这还将保留窗口的位置和大小。

Cascaded Windows Problem 级联Windows问题

One of the problems is that storyboards unlike xibs can include the NSWindowController and Interface Builder doesn't serialize it right. 问题之一是与xibs不同的情节提要可以包含NSWindowController而Interface Builder不能正确序列化它。

-initWithWindow: , -initWithWindowNibName: and friends set shouldCascadeWindows to YES . -initWithWindow: ,- -initWithWindowNibName:和朋友将shouldCascadeWindows设置为YES

When a NSWindowController is loaded from a storyboard via -initWithCoder: , shouldCascadeWindows is NO . 通过shouldCascadeWindows -initWithCoder:从情节shouldCascadeWindows加载NSWindowControllershouldCascadeWindowsNO (OS X 10.11) (作业系统X 10.11)

Based on my tests, this property needs to be set in the initializer. 根据我的测试,需要在初始化程序中设置此属性。 Setting it in -[NSDocument addWindowController:] didn't work. -[NSDocument addWindowController:]进行设置无效。 (OS X 10.11) (作业系统X 10.11)

- (instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self)
    {
        self.shouldCascadeWindows = YES;
    }
    return self;
}

See rdar://47350352 参见rdar:// 47350352

Window Position Problem 窗口位置问题

Using -[NSWindowController windowFrameAutosaveName] or -[NSWindow frameAutosaveName] seems only to work sometimes. 有时仅使用-[NSWindowController windowFrameAutosaveName]-[NSWindow frameAutosaveName] Randomly it uses the initial window position. 它随机使用初始窗口位置。

Window Size Problem 窗口大小问题

Even if the cascaded window position is set right, it never set the size to the one saved for the frame. 即使级联窗口的位置设置正确,也不会将大小设置为为帧保存的大小。 I verified the saved frame with defaults read window.autosavename.test1 . 我使用defaults read window.autosavename.test1验证了保存的帧。 Also before each test I run defaults delete window.autosavename.test1 for a clean state. 同样,在每次测试之前,我都会运行defaults delete window.autosavename.test1以保持干净状态。

Workaround 解决方法

Use a xib containing a empty NSWindow and add the view controllers from the storyboard in -[NSDocument windowControllerDidLoadNib: or -[NSDocument addWindowController:] to the window. 使用包含空NSWindow的xib,然后从-[NSDocument windowControllerDidLoadNib:-[NSDocument addWindowController:]的情节提要中将视图控制器添加到窗口。

I think the answer might be that it's just not possible to have multiple windows share the same frameAutosaveName even though it is possible to have multiple NSSplitView share the same autosaveName . 我认为答案可能是,它只是没有可能有多个窗口共享同一个frameAutosaveName即使它可能有多个NSSplitView共享相同的autosaveName

I just tried creating another NSDocument based project, but this time I used xib's instead of a storyboard. 我只是尝试创建另一个基于NSDocument的项目,但是这次我使用xib而不是一个故事板。 The behavior is better ( shouldCascadeWindows is on by default). 行为会更好(默认情况下应shouldCascadeWindows )。 But new window positioning still breaks down when multiple windows are involved. 但是,当涉及多个窗口时,新窗口的定位仍然会失效。

I think this is more of a runtime constraint then it is storyboard vrs xib problem. 我认为这更多的是运行时约束,那么这是情节提要vrs xib问题。 Here's a test I just did in the default non storyboard NSDocument project generated by Xcode: 这是我刚刚在Xcode生成的默认非故事板NSDocument项目中进行的测试:

  1. Set window autosave name in interface builder. 在界面生成器中设置窗口自动保存名称。

  2. Modify windowControllerDidLoadNib to look like this: 修改windowControllerDidLoadNib如下所示:

     - (void)windowControllerDidLoadNib:(NSWindowController *)aController { [super windowControllerDidLoadNib:aController]; NSLog(@"Listing frameAutosaveName for all windows:"); for (NSWindow *each in [NSApp windows]) { NSLog(@"%@: %@", each.title, each.frameAutosaveName); } } 
  3. And then (after creating a number of windows) this is the output that I see: 然后(在创建多个窗口之后),这是我看到的输出:

     Listing frameAutosaveName for all windows: Untitled: SaveMe Untitled 2: Untitled 3: Untitled 4: Untitled 5: Window: 

So only the first window created gets the "SaveMe" autosave name. 因此,只有第一个创建的窗口会获得“ SaveMe”自动保存的名称。 For all the following windows the value is never set. 对于以下所有以下窗口,永远不会设置该值。

My conclusion is that you just can't use frameAutosaveName to replicate Safari's behavior. 我的结论是,您无法使用frameAutosaveName复制Safari的行为。 Instead you must do something manual. 相反,您必须手动执行一些操作。 I'm not sure if the method used in the example project is the best way, but I think at least some manual work is needed for Safari's behavior no matter if you are using xibs or storyboards. 我不确定示例项目中使用的方法是否是最佳方法,但是我认为,无论您使用的是xibs还是情节提要,Safari的行为至少需要一些手动工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM