Thursday 21 July 2011

NSViewControllers (Part 2)

Following on from the last post which was really the setting up of an NSViewController and we used it to switch views in and out of the window. And really we didn't need very much code to do it. This time we're going to subclass the NSViewController to set some properties in them.

When you create a subclass (using File->New->New File, or apple+N) and you tell Xcode that the parent class is NSViewController it also creates a nib file for that controller. As I was following on from the previous project, I already had the two nib files, so I deleted the newly created ones. Then in the TestView1.xib and TestView2.xib files I had to change the class of the File's Owner to our new NSViewController subclasses (which in my case were TestView1Controller and TestView2Controller) in the Identity Inspector pane on the right. Remember that we also created two NSViewControllers in the MainMenu nib file, so we need to tell Xcode that it should use our new subclasses for those as well. Again just set that in the Identity Inspector pane. Compiling and running showed that everything worked as it did before.

One of the properties that an NSViewController has is a title for the view. This is designed to be displayed somewhere in the UI. I'm going to put it in the title of the NSBox for want of anywhere else to put it. First we need to set the title for each of the controllers.

In the TestView1Controller.m file Xcode has already given us the initWithNibName:bundle: method and that seems like the best place to put it. But if we put code into there we discover that it never gets called. This is because when an object is created from the nib file a different init message is sent: initWithCoder:. We can either put the code in this method or into the awakeFromNib method.


- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    [self setTitle:@"Test view 2"];
    
    return self;
}


Obviously because this is an init method we need to call up to the superclass. Or if we put it into awakeWithNib then all we need is to set the title.



- (void)awakeFromNib
{
    [self setTitle:@"Test View 1"];
}


Finally all we need to do is to set the box title. Back in the action methods we just need to send the setTitle: message to the box like so.



- (IBAction)switchView1:(id)sender
{
    NSView *view = [testView1Controller view];
    
    [box setContentView:view];
    [box setTitle:[testView1Controller title]];
}


Now, if you compile&run the box displays the title that was set in the view controller.
(code for this project available to download http://www.mediafire.com/?h0810n5s808c0u5 Again with the mediafire, fingers crossed...)


We can also set the title with bindings. If we add an NSViewController iVar to the ViewControllerExampleAppDelegate called currentController, then in the bindings inspector pane in Interface Builder we can bind the NSBox's title property to the ViewControllerExampleAppDelegate with keypath being currentController.title. All we have to do to set the box's title is to set currentController to the NSViewController we want displayed. In the new example, I've refactored the duplicated code in the action methods into a method of its own, and now it all looks like this.

- (void)setController:(NSViewController *)controller
{
    NSView *view = [controller view];
    
    [box setContentView:view];
    [self setCurrentController:controller];
}

- (void)awakeFromNib
{
    [self setController:testView1Controller];
}

- (IBAction)switchView1:(id)sender
{
    [self setController:testView1Controller];
}

- (IBAction)switchView2:(id)sender
{
    [self setController:testView2Controller];
}

I had hoped that we could have set the box's contentView via bindings as well, but apparently not.
(code for example 3 available here: http://www.mediafire.com/?k797b2y2uuqjz6c )

There's still some more things to look at on NSViewControllers, I'm working out how to bind things inside the view (if thats possible, I think it is) and I want to look at how NSCollectionView uses view controllers.


Links to the other parts of the NSViewController articles
Part 1:- http://comelearncocoawithme.blogspot.com/2011/07/nsviewcontrollers.html
Part 3:- http://comelearncocoawithme.blogspot.com/2011/08/nsviewcontrollers-part-3.html
Part 4:- http://comelearncocoawithme.blogspot.com/2011/08/nscollectionview-redux.html

No comments:

Post a Comment

Note: only a member of this blog may post a comment.