How to embed a storyboard view controller in an NS

2019-06-03 20:07发布

I'm looking at WWDC 2014 video, "212: Storyboards and controllers on OS X". In this video they claim that Pages UI does/could be arranged using Storyboards on OS X (see below).

Screen capture from 212: Storyboards and controllers on OS X, showing storyboard layout in XCode 6

However, in Pages UI the inspector view is very long and is embedded in a scroll view (you can verify this my two-finger scrolling in Page.app inspector view), also some inspector items are themselves contained in (some type of custom) disclosure view. It doesn't seem to be possible to embed a storyboard view controller in scroll view because there is no corresponding to "scroll view controller" class. Is that right?

How can a storyboard view controller's view be embedded in a scroll view on a storyboard?

I have tried direct embedding at run time, however, this is very hackish and does't work reliably (problems with auto-layout). This route still might be possible, but I wanted to get advice before going too far. For real UI it might be the case of falling back to XIBs.

- (void)viewDidLoad {

    [super viewDidLoad];

    // Swap the view controllers' view for a scroll view
    NSScrollView *scrollView = [[NSScrollView alloc] initWithFrame:self.view.frame];
    scrollView.documentView = self.view;
    scrollView.drawsBackground = NO;
    self.view = scrollView;
}

2条回答
一夜七次
2楼-- · 2019-06-03 20:18

I think this answer is not really solving your problem but maybe helps understanding what is up with storyboards and scrollviews. I think Apple still has to fix some storyboard issues. I tried to use a collection view with storyboards, but it's impossible to connect the collectionViewItem in interface builder (which is happening automatically with xibs).

Here is an example with collection views:

  1. Drag and Drop the collection view to a viewController. You will see a collection view and a collectionViewItem appearing. But the collection view item is NOT connected to the collection view. If you try this using IB, nothing happens.
  2. In Identity inspector of IB assign a Soryboard ID. It's a random name which will be used in the code later. Here I am using "MyCollectionView"
  3. If using swift, select your projects name in Module. The code is mostly the same for objC
  4. Connect the collection view to the ViewController, containing the collection view

Do some coding to connect the Collection View item

class IVMyCollectionViewController: NSViewController, NSCollectionViewDelegate {

// manual connections to collection view (which is not working in IB)
@IBOutlet weak var collectionView: NSCollectionView!

class var sharedInstance : IVMyCollectionViewController {

    struct Static {

        static var instance:IVMyCollectionViewController? = nil
    }

    if Static.instance != nil {

        return Static.instance!
    } else {

        let bundle      = NSBundle.mainBundle()
        let infoDict    = bundle.infoDictionary!
        let sbName      = infoDict["NSMainStoryboardFile"] as String
        let storyboard  = NSStoryboard(name:sbName, bundle:bundle)!
        let vcName      = "MyCollectionView"
        let sbInstance  = storyboard.instantiateControllerWithIdentifier(vcName) as IVMyCollectionViewController

        Static.instance = sbInstance

        return sbInstance
    }
}

// implement your controller

}

That means that some UI elements are not properly implemented yet. I would send a bug report to apple. There is still lots of things missing in interface builder.

Right now I would use a mixture of storyboard and xibs to abuse the storyboard in a way like above, by instantiating the connection in the constructor of the controller. You can use the storyboardID to launch views and other views or load from xibs. You can place viewControllers inside a storyboard without connections (segues) to create a pool of views that can be used like xibs. (A viewController is more or less the same like a xib)

// objC
DetailViewController* controller = [[DetailViewController alloc] initWithNibName:@"DetailView" bundle:nil];

or instantiate using the storyboardID like above.

Try to create a scroll view in storyboard. Create the views which you like to be shown in viewControllers for each view. Your scrollviews view controller should have a connection to the scroll view itself. In the following example the scroll view's outlet is named "self.contentView":

// instantiate a view controller for your scrolling view
self.scrollingViewController = [[ScrollingViewController alloc] initWithNibName:@"ScrollingView" bundle:nil];

// or do the same with storyboards by instantiating view controllers by ID
self.scrollingViewController = [myStoryboard instantiateControllerWithIdentifier:@"MyScrollingViewID"];

// Then set the view from the controller as content view
[self.contentView setDocumentView:self.scrollingViewController.view];
[self.contentView.contentView scrollPoint:NSMakePoint(0., self.scrollingViewController.view.frame.size.height)];

It's exactly like mixing up objective C and swift code. Apple seems to have entered a transition path which was not walked to the end.

In general you should think of View- or WindowControllers in storyboards is the same like a complete xib file. If you would like to use more views, use container views in storyboards. The FilesOwner in xibs is the viewController in storyboards. Container views offer you the ability to create a couple of views attached to a view controller. The segue mechanism is available for containers. I think the scroll view mechanism of OS X is not elegant. I struggled a lot with it, too.

Good luck!

查看更多
Luminary・发光体
3楼-- · 2019-06-03 20:34
  1. Create the view that will be the document view of the scroll view.
  2. Select that view
  3. Go to Editor > Embed In > Scroll View

Based on this page of Scroll View Programming Guide for Mac.

查看更多
登录 后发表回答