I have setup a basic test app that displays a view containing a label, with no use of IB. I want to use a custom UIView subclass AND custom UIViewController subclass.
This will run as anticipated, but the MyViewController’s viewWillAppear and other similar delegates do not fire.
What am I missing to make these fire? In previous projects (using IB), these would fire just fine.
Here is the complete code:
AppDelegate – loads a ‘MainVC’ view controller and sets it as the root controller
#import "AppDelegate.h"
#import "MainVC.h"
@implementation AppDelegate
@synthesize window = _window;
@synthesize mainVC = _mainVC;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.mainVC = [[MainVC alloc] init];
self.window.rootViewController = self.mainVC;
[self.window makeKeyAndVisible];
return YES;
}
MainVC – creates a ‘MyViewController’ which allocates the ‘MyView’ (it also passes down the frame size that should be used for the view)
#import "MainVC.h"
#import "MyViewController.h"
@implementation MainVC
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
MyViewController *controller = [[MyViewController alloc] init];
CGRect frame;
frame.origin.x = 5;
frame.origin.y = 5;
frame.size.width = self.view.frame.size.width - (2 * 5);
frame.size.height = self.view.frame.size.height - (2 * 5);
controller.startingFrame = frame;
[self.view addSubview:controller.view];
}
return self;
}
MyViewController – creates the MyView
#import "MyViewController.h"
#import "MyView.h"
@implementation MyViewController
@synthesize startingFrame;
- (void)loadView{
self.view = [[MyView alloc] initWithFrame:startingFrame];
}
- (void)viewWillAppear:(BOOL)animated{
NSLog(@"appearing"); //doesn't do anything
}
- (void)viewDidAppear:(BOOL)animated{
NSLog(@"appeared"); //doesn't do anything
}
MyView
#import "MyView.h"
@implementation MyView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor whiteColor];
label = [[UILabel alloc] initWithFrame:CGRectMake(20, 20, 150, 40)];
[label setText:@"Label"];
[self addSubview:label];
}
return self;
}
Your mistake: You’re setting a root view controller and then adding another’s view controller view on top of that. While the second view is added to the view hierarchy, its view controller remains “unwired” this way. In fact if you check on your MainViewController’s parentViewController, you will notice it’s
nil.Why: The viewWillAppear method will be sent only to the root view controller or to view controllers in the hierarchy of the root view controller (those that were presented using
presentModalViewController:animated:orpresentViewController:animated:completion:).Solutions: to solve it you have a few options: