I want to interchange views in cocoa MAC app development like UINavigationController for push/pop views in cocoa touch. Its a requirement of the app for push and pop views, somehow i could managed to do achieve this, but now i am in middle of project, i want something like viewWillAppear in cocoa.
5 Answers
Just for informative purposes, iOS View lifecycle methods (viewDidLoad, viewWillAppear, viewDidAppear etc) are available since OSX 10.10 Yosemite (and probably onwards).
And a caution note: If you plan on making an application run on earlier than 10.10 OSX versions, do NOT implement such methods as they will not be recognized by earlier versions (and therefore the code within will not be executed)

- 493
- 7
- 15
Such a method IS NOT available on Mac. OSX UI is very different compared to iOS UI. Use -(void)loadView for initial UI update (or -(void)awakeFromNib if your UI was designed in Interface Builder and loads from a xib file) and after that make specific, on-demand UI update requests, programatically, whenever you call showWindow, makeKeyAndOrderFront, get notifications, get callbacks from delegates, etc.

- 3,346
- 2
- 27
- 39
I came up with somethiing like this:
HEADER:
@protocol GWViewExtensions <NSObject>
- (void) viewWasAddedToSuperview;
@end
@interface GWView : NSView
//set to the view controller managing this view to get NSResponder udpates,
//and GWViewExtension protocol method calls.
@property (weak,nonatomic) IBOutlet NSViewController * viewController;
@end
IMPLEMENTATION:
#import "GWView.h"
@implementation GWView
- (void) awakeFromNib {
[self setNeedsDisplay:TRUE];
}
- (void) addSubview:(NSView *)aView {
[super addSubview:aView];
if([aView isMemberOfClass:[GWView class]]) {
GWView * gview = (GWView *)aView;
if(gview.viewController && [gview.viewController conformsToProtocol:@protocol(GWViewExtensions)]) {
if([gview.viewController respondsToSelector:@selector(viewWasAddedToSuperview)]) {
[gview.viewController performSelectorOnMainThread:@selector(viewWasAddedToSuperview) withObject:nil waitUntilDone:FALSE];
}
}
}
}
- (void) setViewController:(NSViewController *) newController {
if(_viewController) {
NSResponder *controllerNextResponder = [_viewController nextResponder];
[super setNextResponder:controllerNextResponder];
[_viewController setNextResponder:nil];
}
_viewController = newController;
if(newController) {
NSResponder *ownNextResponder = [self nextResponder];
[super setNextResponder:_viewController];
[_viewController setNextResponder:ownNextResponder];
}
}
- (void)setNextResponder:(NSResponder *)newNextResponder {
if(self.viewController) {
[self.viewController setNextResponder:newNextResponder];
return;
}
[super setNextResponder:newNextResponder];
}
- (void) setBackgroundColor:(NSColor *)backgroundColor {
_backgroundColor = backgroundColor;
[self setNeedsDisplay:TRUE];
}
- (void) drawRect:(NSRect) dirtyRect {
[super drawRect:dirtyRect];
if(self.backgroundColor) {
NSGraphicsContext * theContext = [NSGraphicsContext currentContext];
[theContext saveGraphicsState];
[[NSGraphicsContext currentContext] setPatternPhase:NSMakePoint(0,[self frame].size.height)];
[self.backgroundColor set];
NSRectFill([self bounds]);
[theContext restoreGraphicsState];
}
}
- (void) dealloc {
self.backgroundColor = nil;
}
@end
USE:
#import <Cocoa/Cocoa.h>
#import "GWView.h"
@interface GWDribbbleShotDetailColumn : NSViewController <GWViewExtensions>
@end
#import "GWDribbbleShotDetailColumn.h"
@interface GWDribbbleShotDetailColumn ()
@end
@implementation GWDribbbleShotDetailColumn
- (void) viewWasAddedToSuperview {
NSRect svb = self.view.superview.bounds;
NSRect sf = self.view.frame;
sf.size.height = NSHeight(svb);
sf.size.width = NSWidth(svb);
self.view.frame = sf;
}
@end

- 5,902
- 4
- 43
- 56
I use a special view for NSViewController, which calls back the view controller. You can extend the code to have methods like viewWillAppear.
- (void)viewWillMoveToWindow:(NSWindow *)newWindow {
[super viewWillMoveToWindow:newWindow];
if (self.installed && !newWindow) {
[self viewWillUninstall];
NSViewController<SMControllerViewDelegate> *viewController = self.viewController;
if (viewController) {
@autoreleasepool {
[viewController viewWillUninstall];
}
}
}
}
- (void)viewDidMoveToWindow {
[super viewDidMoveToWindow];
if (!self.installed && self.window) {
[self viewDidInstall];
NSViewController<SMControllerViewDelegate> *viewController = self.viewController;
if (viewController) {
@autoreleasepool {
[viewController viewDidInstall];
}
}
}
}

- 952
- 4
- 18
i have used NSViewController for changing the views like set the viewController on window on button click as needed, but what i discovered is once the (id)init gets called for a particular viewController, it never calls again for that same viewController.For that reason my UI (View / MVC) is not updating. i forcefully called the (id)init again but view is not refreshing.

- 1