【问题标题】:Xcode 9 storyboard window position autosaveXcode 9故事板窗口位置自动保存
【发布时间】:2018-04-20 07:56:27
【问题描述】:

我在 Xcode 9(采用 SceneKit 技术的 macOS 游戏)中开始新项目。我的故事板包含NSWindowControllerNSWindow 以及相关的GameViewControllerSCNView。项目运行良好(旋转飞机)。

现在在情节提要中,我将 NSWindow 的自动保存值设置为“MainWindow”,运行项目,调整窗口大小然后退出。我知道在退出窗口位置设置自动保存将使用NSUserDefaults 保存,所以我在终端检查:

$ defaults read com.koati.Bloks                                           ⏎
{
    "NSWindow Frame MainWindow" = "415 228 450 322 0 0 1280 777 ";
}

这是预期的行为。现在我再次运行项目,但我看到窗口位置没有恢复。如果在情节提要中删除GameViewController 关系,则位置会被正确保存和恢复,所以我认为GameViewController 会以某种方式影响窗口大小和位置。 在带有 XIB 的旧 Xcode 中没有这样的问题。

编辑:经过一些测试,我现在认为它与 SceneKit 完全无关,因为在 NSViewController 中将 SCNView 替换为 NSView 会产生相同的结果。所以我认为问题在于 NSViewController 通过 Storyboard 附加到 NSWindow 内容会影响窗口位置和大小。

也许有人知道如何解决这个问题?

【问题讨论】:

  • 我遇到了同样的问题,同意你的观察。我有一个针对这个问题的测试项目。来自模板的默认值:Window->View Controller->View 保留位置和大小。如果我替换为 Window->Split View Controller->View 它不会保留位置和大小(始终返回默认位置和大小)。如果我再次执行 Window->View Controller->View->Container View->Split View Controller->View,它会保留大小和位置。

标签: macos cocoa storyboard xcode9


【解决方案1】:

奇怪的是,这个答案:https://stackoverflow.com/a/33707356/3736845 即使在 XCode9 中仍然适用。自动保存名称的编程设置后(对于 Swift4 有点不同的符号):

class MainWindowController: NSWindowController {

  override func windowDidLoad() {
    super.windowDidLoad()

    // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
    self.windowFrameAutosaveName = NSWindow.FrameAutosaveName.init(rawValue: "position")
  }
}

它在应用程序重新启动时开始恢复位置。

但我不明白的是保存到默认值中的内容:

defaults read com.ne.TestWindowPosition
{
   "NSWindow Frame Position" = "510 428 901 322 0 0 1920 1177 ";
   "NSWindow Frame position" = "0 0 901 322 0 0 1920 1177 ";
}

我对 IB Window Autosave 标识符进行了一些尝试 - 您会看到它显示为默认值(“Position”)中的第一行,并且在应用程序启动时似乎无法正确读取。 在我将手动设置的自动保存名称添加到“位置”之后 - 当我移动窗口时它正在改变。

【讨论】:

  • 不好的是我需要使用额外的 NSWindowController 来实现默认的 IB 功能。看起来像一个错误。
【解决方案2】:

这似乎是 Xcode 10 中仍然存在的错误。这对我有用(在 Xcode 10 中,在使用故事板的 macOS Cocoa 项目中):

• 情节提要窗口的自动保存字段中没有设置值。

• 使用如下自定义窗口控制器类。

import AppKit


class WindowController: NSWindowController {

    override func windowDidLoad() {
        super.windowDidLoad()
        //---------------------------------------------------------------------
        // Workaround for a bug in autosave default for window frame:
        window!.setFrameAutosaveName("position")
        // It has to be "position" here in code, and no value in storyboard.
        //---------------------------------------------------------------------
    }
}

【讨论】:

  • 请记住,框架的每个名称都必须是唯一的。这意味着,如果您有多个窗口,请为每个窗口创建一个具有自己名称的类。可能不是最漂亮的解决方案,但如果您的 Mac 应用程序中只有几个其他窗口,它会很好地工作。
猜你喜欢
  • 2021-01-12
  • 2015-08-20
  • 1970-01-01
  • 2015-11-30
  • 1970-01-01
  • 2017-11-15
  • 2018-04-15
  • 1970-01-01
  • 2017-12-15
相关资源
最近更新 更多