Ok, so here’s how you use a nib file (at least one way of doing it, but it’s the one that makes most sense to me…).
First, change the model. In the AppDelegate file’s ‘applicationWillFinishLaunching:’ handler, change the list of dictionaries to add a new value “nibName” that holds the name of the nib we want to invoke. It should look something like this:
set sidebarList to {{title:"Header 1", isHeader:true, nibName:""}, {title:"Line 1", isHeader:false, nibName:"Line1"}, {title:"Header 2", isHeader:true, nibName:""}, {title:"Line 2", isHeader:false, nibName:"Line2"}, {title:"Line 3", isHeader:false, nibName:"Line3"}, {title:"Header 3", isHeader:true, nibName:""}, {title:"Line 4", isHeader:false, nibName:"Line4"}}
Next, create a view controller. Add a new blank file to the project: Choose New File, scroll down to the ‘Other’ section, choose ‘Empty’, and then click the ‘Next’ Button. Name the file “MyViewController.applescript” (or whatever makes sense to you, with a .applescript extension). Open this new file and edit in the following:
script MyViewController
property parent: class "NSViewController"
on initWithNibName:nibName bundle:bundle
continue initWithNibName:nibName bundle:bundle
end
on loadView()
continue loadView()
end
end script
The parent class has to be NSViewController (it defualts, I think, to NSObject), the name of the script is the name of the class you’ll invoke later, and you’ll need to override at least these two methods explicitly. continue is the AppleScript equivalent of ‘super’, so all you’re really doing here is telling the subclass to call the objective-C class implementations. You’ll probably need to do on override like this for any method you call explicitly from AppleScript, should you decide to expand.
Next, create your xib files. Choose New File, scroll down to the ‘User Interface’ section, choose ‘View’, and then click the ‘Next’ Button. Use the names in your data model (e.g., if a ‘nibName’ in the model is “Line2” you should have a name corresponding file Line2.xib; I believe Xcode will automatically add the xib extension). Construct the contents of the view as you see fit, then do this:
- In the xib view, click on File’s Owner
- Click on the Identity inspector, and make sure the file’s owner class is “MyViewController”, or whatever you named your view controller class. It has to correspond to the first line of the file: “script MyViewController”
- Click on the Connections inspector, and drag to connect the ‘view’ outlet of the File’s Owner to the top-level of the view you’ve created.
Of course, here you’ll have to do whatever bindings and connection you want to make for this particular view. Anything you set as a property in the view controller can be accessed by the view through the parent object, and that’s how you’ll pass data into the view. But I’m sure you can figure that out.
Now you’re ready to go: back in the AppDelegate file, change the ‘tableViewSelectionDidChange’ like so (note again that I’m using the classname ‘MyViewController’, but you may end up changing that):
on tableViewSelectionDidChange:aNotification
set tableView to aNotification's object
set selectedRowIdx to (tableView's selectedRow) as integer
set rowData to arrayController's arrangedObjects's objectAtIndex:selectedRowIdx
set theNibName to (rowData's nibName) as text
if theNibName is not "" then
set viewController to current application's class "MyViewController"'s alloc's initWithNibName:(rowData's nibName) bundle:(current application's NSBundle's mainBundle)
viewController's loadView()
set theView to viewController's view
set theView's translatesAutoresizingMaskIntoConstraints to false
set detailSubviews to (detailView's subviews) as list
if detailSubviews is not {} then
set oldLabel to item 1 of detailSubviews
detailView's replaceSubview:oldLabel |with|:theView
else
detailView's addSubview:theView
end
(* set view constraints *)
set constraintLeading to theView's leadingAnchor's constraintEqualToAnchor:(detailView's leadingAnchor)
set constraintTop to theView's topAnchor's constraintEqualToAnchor:(detailView's topAnchor)
set constraintBottom to theView's bottomAnchor's constraintEqualToAnchor:(detailView's bottomAnchor)
set constraintTrailing to theView's trailingAnchor's constraintEqualToAnchor:(detailView's trailingAnchor)
constraintLeading's setActive:true
constraintTop's setActive:true
constraintBottom's setActive:true
constraintTrailing's setActive:true
end if
end
All this does is create a view for the appropriate xib, load its view, and then add and constrain that view to the detailView, as before.
Just so it’s said, best practice would really be to eliminate the detailView object and use an NSLayoutGuide instead, but this approach strikes me as more accessible.