Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
416 views
in Technique[技术] by (71.8m points)

cocoa - Using an NSArrayController in Multiple Storyboard Scenes

I have a Mac document-based Core Data application that uses storyboards. The storyboard has the following layout:

Window Controller
    Split View Controller
        Table View Controller
        Text View Controller

My Core Data model contains a Chapter entity that contains two attributes: title and contents. I want the table view to show each chapter title. The text view shows the contents of the selected chapter.

If I was using a xib file, I would add an array controller to the xib file. I would bind the array controller to File's Owner to access my NSPersistentDocument subclass. I would bind the table view to the array controller's arrangedObjects property and bind the text view to the array controller's selection.

But with storyboards things get more complicated. I can add an array controller to the table view controller, bind the table view to the array controller, and have the chapter titles show up in the table view. But the text view controller can't bind to that array controller because the array controller is in another scene.

How do I add an array controller in Interface Builder so that both the table view controller and text view controller can access it and bind to it?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The key to making this work is to have a NSArrayController instance in each of your descending NSViewController subclasses and binding them together through a central data source (most likely your NSDocument subclass). You can then set this data source as your NSViewController subclasses representedObject by passing it down through your descending controllers. Here is an example of a storyboard application with an NSWindowController which has a content view controller that is a NSSplitViewController with two child view controllers (A Master / Detail setup):

class Document: NSDocument {

    var dataSource: DataSource? = DataSource()

    ...
}

class DataSource: NSObject, NSCoding {

    var items: [Item] = []
    var selectionIndexes: NSIndexSet = NSIndexSet()

    ...
}

class WindowController: NSWindowController {

    override var document: AnyObject? {
        didSet {
            if let document = self.document as? Document {
                self.contentViewController?.representedObject = document
            }
        }
    }

}

class SplitViewController: NSSplitViewController {

    override var representedObject: AnyObject? {
        didSet {
            for viewController in self.childViewControllers as! [NSViewController] {
                viewController.representedObject = representedObject
            }
        }
    }
}

The trick is to bind the representedObject to each of your descending view controller's NSArrayController in the storyboard. You need to bind NOT ONLY the contentArray BUT ALSO the selectionIndexes.

The result is that the selectionIndexes on both descending NSArrayControllers are kept in sync because they are bound through the central data source (DataSource subclass in above example).

To make this all clearer I have created an example project that demonstrates this here: https://github.com/acwright/StoryboardBindingsExample


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...