Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial commit.

  • Loading branch information...
commit de7151367540e49a28b7cf2f979c52fec701d9e6 0 parents
@joshaber authored
37 JAViewController.h
@@ -0,0 +1,37 @@
+//
+// JAViewController.h
+//
+// Created by Josh Abernathy on 8/17/10.
+// Copyright (c) 2010 Maybe Apps. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+
+@interface JAViewController : NSViewController {
+
+}
+
++ (id)viewController;
+
+- (void)viewDidLoad;
+
+// Called when the view has a superview and window. This does not necessarily mean the view is visible.
+- (void)viewWillAppear;
+- (void)viewDidAppear;
+
+// Called when the view no longer has a superview or no longer has a window.
+- (void)viewWillDisappear;
+- (void)viewDidDisappear;
+
+- (void)viewWillMoveToSuperview:(NSView *)newSuperview;
+- (void)viewDidMoveToSuperview;
+- (void)viewWillBeRemovedFromSuperview;
+- (void)viewWasRemovedFromSuperview;
+
+- (void)viewWillMoveToWindow:(NSWindow *)newWindow;
+- (void)viewDidMoveToWindow;
+- (void)viewWillBeRemovedFromWindow;
+- (void)viewWasRemovedFromWindow;
+
+@end
82 JAViewController.m
@@ -0,0 +1,82 @@
+//
+// JAViewController.m
+//
+// Created by Josh Abernathy on 8/17/10.
+// Copyright (c) 2010 Maybe Apps. All rights reserved.
+//
+
+#import "JAViewController.h"
+#import "NSView+JAExtensions.h"
+
+
+@implementation JAViewController
+
++ (id)viewController {
+ return [[[self alloc] initWithNibName:NSStringFromClass([self class]) bundle:nil] autorelease];
+}
+
+- (void)loadView {
+ [super loadView];
+
+ [self viewDidLoad];
+}
+
+- (void)setView:(NSView *)view {
+ [super setView:view];
+
+ self.view.viewController = self;
+}
+
+- (void)viewDidLoad {
+
+}
+
+- (void)viewWillAppear {
+ [self.view setNeedsLayout];
+}
+
+- (void)viewDidAppear {
+
+}
+
+- (void)viewWillDisappear {
+
+}
+
+- (void)viewDidDisappear {
+
+}
+
+- (void)viewWillMoveToSuperview:(NSView *)newSuperview {
+
+}
+
+- (void)viewDidMoveToSuperview {
+
+}
+
+- (void)viewWillBeRemovedFromSuperview {
+
+}
+
+- (void)viewWasRemovedFromSuperview {
+
+}
+
+- (void)viewWillMoveToWindow:(NSWindow *)newWindow {
+
+}
+
+- (void)viewDidMoveToWindow {
+
+}
+
+- (void)viewWillBeRemovedFromWindow {
+
+}
+
+- (void)viewWasRemovedFromWindow {
+
+}
+
+@end
13 NSObject+JAExtensions.h
@@ -0,0 +1,13 @@
+//
+// NSObject+JAExtensions.h
+//
+// Created by Josh Abernathy on 8/18/10.
+// Copyright (c) 2010 Maybe Apps. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+
+@interface NSObject (JAExtensions)
++ (void)swapMethod:(SEL)originalSelector with:(SEL)newSelector;
+@end
28 NSObject+JAExtensions.m
@@ -0,0 +1,28 @@
+//
+// NSObject+JAExtensions.m
+//
+// Created by Josh Abernathy on 8/18/10.
+// Copyright (c) 2010 Maybe Apps. All rights reserved.
+//
+
+#import "NSObject+JAExtensions.h"
+#import <objc/runtime.h>
+
+
+@implementation NSObject (JAExtensions)
+
++ (void)swapMethod:(SEL)originalSelector with:(SEL)newSelector {
+ Method originalMethod = class_getInstanceMethod(self, originalSelector);
+ Method newMethod = class_getInstanceMethod(self, newSelector);
+ const char *originalTypeEncoding = method_getTypeEncoding(originalMethod);
+ const char *newTypeEncoding = method_getTypeEncoding(newMethod);
+ NSAssert2(!strcmp(originalTypeEncoding, newTypeEncoding), @"Method type encodings must be the same: %s vs. %s", originalTypeEncoding, newTypeEncoding);
+
+ if(class_addMethod(self, originalSelector, method_getImplementation(newMethod), newTypeEncoding)) {
+ class_replaceMethod(self, newSelector, method_getImplementation(originalMethod), originalTypeEncoding);
+ } else {
+ method_exchangeImplementations(originalMethod, newMethod);
+ }
+}
+
+@end
17 NSView+JAExtensions.h
@@ -0,0 +1,17 @@
+//
+// NSView+JAExtensions.h
+//
+// Created by Josh Abernathy on 8/18/10.
+// Copyright (c) 2010 Maybe Apps. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+
+@interface NSView (JAExtensions)
+- (void)layoutSubviews;
+- (void)layoutIfNeeded;
+- (void)setNeedsLayout;
+
+@property (nonatomic, assign) IBOutlet NSViewController *viewController;
+@end
223 NSView+JAExtensions.m
@@ -0,0 +1,223 @@
+//
+// NSView+JAExtensions.m
+//
+// Created by Josh Abernathy on 8/18/10.
+// Copyright (c) 2010 Maybe Apps. All rights reserved.
+//
+
+#import "NSView+JAExtensions.h"
+#import "NSObject+JAExtensions.h"
+#import "JAViewController.h"
+#import <objc/runtime.h>
+
+@interface NSView ()
++ (void)loadSupportForLayoutSubviews;
++ (void)loadSupportForViewControllers;
+
+- (void)custom_viewWillMoveToSuperview:(NSView *)newSuperview;
+- (void)custom_viewDidMoveToSuperview;
+
+- (void)custom_viewWillMoveToWindow:(NSWindow *)newWindow;
+- (void)custom_viewDidMoveToWindow;
+
+- (void)custom_setNextResponder:(NSResponder *)newNextResponder;
+
+- (void)custom_setBounds:(NSRect)newBounds;
+- (void)custom_setFrame:(NSRect)newFrame;
+- (void)custom_viewWillDraw;
+- (BOOL)needsLayout;
+@end
+
+static NSString * const JAViewExtensionsViewControllerKey = @"JAViewExtensionsViewControllerKey";
+static NSString * const JAViewExtensionsNeedsLayoutKey = @"JAViewExtensionsNeedsLayoutKey";
+
+static BOOL hasSwizzledViewControllerMethods = NO;
+
+
+@implementation NSView (JAExtensions)
+
++ (void)initialize {
+ if(self == [NSView class]) {
+ [self loadSupportForLayoutSubviews];
+ }
+}
+
+
+#pragma mark UIView -layoutSubviews support
+
++ (void)loadSupportForLayoutSubviews {
+ [self swapMethod:@selector(setBounds:) with:@selector(custom_setBounds:)];
+ [self swapMethod:@selector(setFrame:) with:@selector(custom_setFrame:)];
+ [self swapMethod:@selector(viewWillDraw) with:@selector(custom_viewWillDraw)];
+}
+
+- (void)custom_setBounds:(NSRect)newBounds {
+ [self custom_setBounds:newBounds];
+
+ [self setNeedsLayout];
+}
+
+- (void)custom_setFrame:(NSRect)newFrame {
+ [self custom_setFrame:newFrame];
+
+ [self setNeedsLayout];
+}
+
+- (void)custom_viewWillDraw {
+ [self layoutIfNeeded];
+
+ [self custom_viewWillDraw];
+}
+
+- (void)layoutIfNeeded {
+ if([self needsLayout]) {
+ [self layoutSubviews];
+ }
+}
+
+- (void)layoutSubviews {
+ objc_setAssociatedObject(self, JAViewExtensionsNeedsLayoutKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (void)setNeedsLayout {
+ objc_setAssociatedObject(self, JAViewExtensionsNeedsLayoutKey, [NSNull null], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+
+ [self setNeedsDisplay:YES];
+}
+
+- (BOOL)needsLayout {
+ return objc_getAssociatedObject(self, JAViewExtensionsNeedsLayoutKey) != nil;
+}
+
+
+#pragma mark NSViewController support
+
++ (void)loadSupportForViewControllers {
+ @synchronized(self) {
+ if(hasSwizzledViewControllerMethods) return;
+
+ [self swapMethod:@selector(viewWillMoveToSuperview:) with:@selector(custom_viewWillMoveToSuperview:)];
+ [self swapMethod:@selector(viewDidMoveToSuperview) with:@selector(custom_viewDidMoveToSuperview)];
+
+ [self swapMethod:@selector(viewWillMoveToWindow:) with:@selector(custom_viewWillMoveToWindow:)];
+ [self swapMethod:@selector(viewDidMoveToWindow) with:@selector(custom_viewDidMoveToWindow)];
+
+ [self swapMethod:@selector(setNextResponder:) with:@selector(custom_setNextResponder:)];
+
+ hasSwizzledViewControllerMethods = YES;
+ }
+}
+
+- (void)setViewController:(NSViewController *)newViewController {
+ // swizzle methods only after we make use of the viewController property
+ [[self class] loadSupportForViewControllers];
+
+ if(self.viewController != nil) {
+ NSResponder *controllerNextResponder = [self.viewController nextResponder];
+ [self custom_setNextResponder:controllerNextResponder];
+ [self.viewController setNextResponder:nil];
+ }
+
+ objc_setAssociatedObject(self, JAViewExtensionsViewControllerKey, newViewController, OBJC_ASSOCIATION_ASSIGN);
+
+ if(newViewController != nil) {
+ NSResponder *ownNextResponder = [self nextResponder];
+ [self custom_setNextResponder:self.viewController];
+ [self.viewController setNextResponder:ownNextResponder];
+ }
+}
+
+- (NSViewController *)viewController {
+ return objc_getAssociatedObject(self, JAViewExtensionsViewControllerKey);
+}
+
+- (void)custom_viewWillMoveToSuperview:(NSView *)newSuperview {
+ [self custom_viewWillMoveToSuperview:newSuperview];
+
+ if([self.viewController isKindOfClass:[JAViewController class]]) {
+ if(newSuperview == nil) {
+ [(JAViewController *) self.viewController viewWillBeRemovedFromSuperview];
+
+ if(self.superview != nil && self.window != nil) {
+ [(JAViewController *) self.viewController viewWillDisappear];
+ }
+ } else {
+ [(JAViewController *) self.viewController viewWillMoveToSuperview:newSuperview];
+
+ if(self.window != nil) {
+ [(JAViewController *) self.viewController viewWillAppear];
+ }
+ }
+ }
+}
+
+- (void)custom_viewDidMoveToSuperview {
+ [self custom_viewDidMoveToSuperview];
+
+ if([self.viewController isKindOfClass:[JAViewController class]]) {
+ if(self.superview == nil) {
+ [(JAViewController *) self.viewController viewWasRemovedFromSuperview];
+
+ if(self.window == nil) {
+ [(JAViewController *) self.viewController viewDidDisappear];
+ }
+ } else {
+ [(JAViewController *) self.viewController viewDidMoveToSuperview];
+
+ if(self.window != nil) {
+ [(JAViewController *) self.viewController viewDidAppear];
+ }
+ }
+ }
+}
+
+- (void)custom_viewWillMoveToWindow:(NSWindow *)newWindow {
+ [self custom_viewWillMoveToWindow:newWindow];
+
+ if([self.viewController isKindOfClass:[JAViewController class]]) {
+ if(newWindow == nil) {
+ [(JAViewController *) self.viewController viewWillBeRemovedFromWindow];
+
+ if(self.superview != nil && self.window != nil) {
+ [(JAViewController *) self.viewController viewWillDisappear];
+ }
+ } else {
+ [(JAViewController *) self.viewController viewWillMoveToWindow:newWindow];
+
+ if(self.superview != nil) {
+ [(JAViewController *) self.viewController viewWillAppear];
+ }
+ }
+ }
+}
+
+- (void)custom_viewDidMoveToWindow {
+ [self custom_viewDidMoveToWindow];
+
+ if([self.viewController isKindOfClass:[JAViewController class]]) {
+ if(self.window == nil) {
+ [(JAViewController *) self.viewController viewWasRemovedFromWindow];
+
+ if(self.superview == nil) {
+ [(JAViewController *) self.viewController viewDidDisappear];
+ }
+ } else {
+ [(JAViewController *) self.viewController viewDidMoveToWindow];
+
+ if(self.superview != nil) {
+ [(JAViewController *) self.viewController viewDidAppear];
+ }
+ }
+ }
+}
+
+- (void)custom_setNextResponder:(NSResponder *)newNextResponder {
+ if(self.viewController != nil) {
+ [self.viewController setNextResponder:newNextResponder];
+ return;
+ }
+
+ [self custom_setNextResponder:newNextResponder];
+}
+
+@end
Please sign in to comment.
Something went wrong with that request. Please try again.