如何更改Window的内容视图?

时间:2015-07-23 09:40:09

标签: swift cocoa nswindow nsviewcontroller

我正在开发一个mac osx应用程序,它具有从主故事板启动的初始窗口和viewcontroller。我想用我的视图替换storyboard加载的内容视图。 我这样做 -

func replaceContentView() {
  parentViewController =  MainViewController(nibName: "MainContainerView", bundle: nil)!
  let fullScreenFrame = NSScreen.mainScreen()?.visibleFrame
  self.initialWindow.setFrame(fullScreenFrame!, display: false, animate: false)
  self.initialWindow.contentView = parentViewController! . view
}

这种方法的问题是默认的viewcontroller永远不会被释放。根本没有调用默认viewController的 deinit()。 这导致内存泄漏。那么如何完全删除默认内容视图和关联的viewcontroller?

3 个答案:

答案 0 :(得分:0)

你可以用deinit方法编写代码,它可以帮到你。

 deinit {
// perform the deinitialization
}

答案 1 :(得分:0)

您在NSWindow实例中的contentViewController仍然强烈支持其旧视图。您已在NSWindow实例上替换了仅属性。

澄清你做了什么:

  1. NSWindow坚决反对新观点
  2. NSViewController强烈反对旧视图
  3. 您应该将新视图分配到contentViewController.view属性

    这可能会有所帮助:

    NSWindow.h
    
    /* NSViewController Support */
    
    /* The main content view controller for the window. This provides the contentView of the window. Assigning this value will remove the existing contentView and will make the contentViewController.view the main contentView for the window. The default value is nil. The contentViewController only controls the contentView, and not the title of the window. The window title can easily be bound to the contentViewController with the following: [window bind:NSTitleBinding toObject:contentViewController withKeyPath:@"title" options:nil]. Setting the contentViewController will cause the window to resize based on the current size of the contentViewController. Autolayout should be used to restrict the size of the window. The value of the contentViewController is encoded in the NIB. Directly assigning a contentView will clear out the rootViewController.
     */
    @availability(OSX, introduced=10.10)
    var contentViewController: NSViewController?
    
    
    /* The view controller for the window's contentView. Tracks the window property of the same name.
     */
    @property (strong) NSViewController *contentViewController NS_AVAILABLE_MAC(10_10);
    

    但是,如果在启动时执行此操作,您所执行的操作似乎不正确。

    您可以将contentView的自定义子类设置为新的nsview子类,该子类可以从另一个XIB加载它的视图(不需要故事板)。

    抽象示例:

    class CustomView: NSView {
    
        @IBOutlet var contentView: NSView!
        @IBOutlet weak var label: NSTextField!
    
        required init(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            initSubviews()
        }
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            initSubviews()
        }
    
        func initSubviews() {
            let nib = NSNib(nibName: "CustomView", bundle: nil)
            nib.instantiateWithOwner(self, topLevelObjects: nil)
            contentView.frame = bounds
            addSubview(contentView)
        }
    }
    

    PS:topLevelObjects设置为nil,因为你持有强大的contentView。所以不必担心内存管理。

答案 2 :(得分:0)

故事板不处理视图,它们处理视图控制器。情节提要板将视图加载到窗口中时的作用是创建一个NSViewController然后进入

windowController.contentViewController = theViewController

这也隐式地插入theViewController.view作为窗口的内容视图。这样做也是一样,一切都会好起来的。

Marek的示例是错误的,因为CustomView不应该是NSView的子类,它应该是CustomViewController的类,该类拥有包含标签等的视图。作为奖励,{ {1}}还将为您加载XIB。

或者,您可以设置NSViewController(这将删除旧的视图控制器及其内容视图),然后设置内容视图。但是,实际上,为什么正是在windowController.contentViewController = nil打算使用的框架下使用框架?