Автосохранение положения окна раскадровки Xcode 9

Я начинаю новый проект в Xcode 9 (игра для macOS с технологией SceneKit). Я получил раскадровку, содержащую NSWindowController с NSWindow и связанную GameViewController с SCNView. Проект работает нормально (крутит самолет).

Теперь в раскадровке я устанавливаю значение автосохранения на «MainWindow» для NSWindow, запускаю проект, изменяю размер окна и затем выхожу. Я знаю, что с установленным автосохранением при выходе положение окна будет сохранено с помощью NSUserDefaults, поэтому я проверяю в Терминале:

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

Это ожидаемое поведение. Теперь я запускаю проект еще раз, но вижу, что положение окна не восстанавливается. Если в раскадровке удалить отношение GameViewController, то позиция сохраняется и восстанавливается корректно, поэтому я предполагаю, что GameViewController как-то влияет на размер и позицию окна. В более старых Xcode с XIB такой проблемы не было.

EDIT: После некоторых тестов я теперь думаю, что это вообще не связано со SceneKit, так как замена SCNView на NSView в NSViewController дает те же результаты. Итак, я думаю, проблема в том, что NSViewController, прикрепленный через раскадровку к содержимому NSWindow, влияет на положение и размер окна.

Может кто знает как решить эту проблему?


person Ef Dot    schedule 07.11.2017    source источник
comment
Я сталкиваюсь с той же проблемой и согласен с вашим наблюдением. У меня есть тестовый проект для этой проблемы. По умолчанию из шаблона: Window->View Controller->View сохраняет положение и размер. Если я заменю на Window->Split View Controller->View, он не сохранит положение и размер (всегда возвращаюсь к положению и размеру по умолчанию). Если я делаю это Window->View Controller->View->Container View->Split View Controller->View, опять же, он сохраняет размер и положение.   -  person Nick Entin    schedule 14.11.2017


Ответы (2)


Как ни странно, этот ответ: 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 - вы видите, что он отображается в качестве первой строки в настройках по умолчанию ("Позиция") и, кажется, не читается должным образом при запуске приложения. После того, как я добавил ручное задание имени автосохранения в "position" - оно меняется, когда я перемещаю окно.

person Nick Entin    schedule 14.11.2017
comment
Плохо то, что мне нужно использовать дополнительный NSWindowController только для реализации функциональности IB по умолчанию. Похоже на ошибку. - person Ef Dot; 15.11.2017

Это похоже на ошибку, которая все еще присутствует в 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.
        //---------------------------------------------------------------------
    }
}
person Jens    schedule 21.10.2018
comment
Помните, что каждое имя фрейма должно быть уникальным. Это означает, что если у вас несколько окон, создайте класс для каждого окна со своим именем. Вероятно, это не самое красивое решение, но оно хорошо работает, если в вашем приложении Mac есть только несколько других окон. - person Philip Borges; 17.04.2020