Search code examples
objective-cmacoscocoanssplitview

How to force all subviews of NSSplitView to be visible at startup?


I am making a UI completely programmatically. (no IB) I made a NSWindow, and attached a NSSplitView. The problem is first subview of the split-view always become collapsed when window shows up at program startup.

How can I force to show all the subviews of the split-view at start-up?


Solution

  • This kind of problem is hard to prove the reason because it needs knowledge of internals of closed source program.

    So reason unknown, but subviews are shown when I set NSSplitView's initial size to non-zero value before adding subviews.

    NSSplitView* v  = [[NSSplitView alloc] init];
    NSView*      v2 = [[NSView alloc] init];
    v.frame  = NSRectFromCGRect(CGRectMake(0,0,100,100));  // Added this line.
    v2.frame = NSRectFromCGRect(CGRectMake(0,0,50,100));  // Added this line.
    [v addSubview:v2];  // And then, add subview. 
    

    I guess NSSplitView has some internal subview layout behavior by it's current available size. As far as I observed,

    • Adding subviews to zero sized NSSplitView never work correctly.

    Update

    Starting with OS X 10.10, Cocoa introduced a new class NSSplitViewController, and it works quiet nicely. I strongly recommend to use this. It's fully auto-layout based, so you need to use auto-layout constraints to set sizes.

    I wrote a working example project, and here's copied code snippets.

        func make1() -> NSViewController {
            let vc1     =   NSViewController()
            vc1.view    =   NSView()
            vc1.view.wantsLayer =   true
            vc1.view.layer!.backgroundColor =   NSColor.blueColor().CGColor
            return  vc1
        }
        func setup1(vc1:NSViewController) {
            /// Layout constraints must be installed after the view is added to a view hierarchy.
            split1.view.addConstraint(NSLayoutConstraint(item: vc1.view, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.GreaterThanOrEqual, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 0, constant: 20))
            split1.view.addConstraint(NSLayoutConstraint(item: vc1.view, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.LessThanOrEqual, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 0, constant: 300))
        }
    
        split1.addSplitViewItem(NSSplitViewItem(viewController: make1()))
        split1.addSplitViewItem(NSSplitViewItem(viewController: make1()))
        split1.addSplitViewItem(NSSplitViewItem(viewController: make1()))
    
        setup1(split1.splitViewItems[0].viewController)
        setup1(split1.splitViewItems[1].viewController)
        setup1(split1.splitViewItems[2].viewController)