Can anyone explain why viewDidLoad does not get called when loadView is used? It's my understanding that viewDidLoad should still get called.
- (void)loadView
{
CGRect currentFrame = [[UIScreen mainScreen] applicationFrame];
UIView* myView = [[UIView alloc] initWithFrame:CGRectMake(currentFrame.origin.x, currentFrame.origin.y, currentFrame.size.width, currentFrame.size.height)];
myView.backgroundColor = [UIColor redColor];
self.view = myView;
[myView release];
[super loadView];
}
- (void)viewDidLoad {
//this never happens
NSLog(#"VIEW DID LOAD!");
[super viewDidLoad];
}
I've just found out that viewDidLoad won't be called if you call loadView manually in your application.
If you call loadView manually you have to call viewDidLoad manually as well.
More over according to apple docs you shouldn't call [super loadView] as it will overwrite your view with a default UIView.
You must have a warning here:
NSLog("VIEW DID LOAD!");
Instead, you should write like this (the # sign is necessary):
NSLog(#"VIEW DID LOAD!");
viewDidLoad will not get called when you create instance of ViewController. When you are pushing it to navigation controller or present it as model viewcontroller, then only the viewDidLoad get called. Until and unless you are presenting viewController, these delegate will not get called. And one more thing, if your viewcontroller presentation over, and still it remains in the stack or memory, then viewDidLoad method will not get called again because its already load the view. Then viewWillAppear and viewDidAppear delegates only get called when you present the same viewController.
Related
when set self.view.tag is 10 in loadView ,but in viewDidload it's tag is 0
why ? thanks
- (void)loadView
{
[super loadView];
NSLog(#"loadView %d",self.view.tag);
[self.view setTag:10];
self.view = [[UIView alloc] initWithFrame:self.view.frame];
self.view.backgroundColor = [UIColor yellowColor];
}
#pragma mark view loaded
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"ViewDidload %d",self.view.tag);
[self.view setTag:10];
}
The loadView method is not usually implemented. The system calls it in order to create your view hierarchy. At the time it's called, your views will not exist.
Why are you implementing loadView? You probably should not be.
To quote the docs:
If you use Interface Builder to create your views and initialize the
view controller, you must not override this method.
What code are you putting in your loadView method?
I want to know what notification would I get in my CustomView class when this view will be displayed on screen.
CustomView *customView = [[CustomView alloc] init];
[self.view addSubview:customView];
NewViewController *newController = [[NewViewController alloc] init];
[self.navigationController pushViewController:newController animated:YES];
and after some work I pop this viewController.
[self.navigationController popViewControllerAnimated:YES];
I want to know what method in CustomView class will be called when that view will appear again on the screen.
Actually I have an infinite loop animation in that CustomView and on pushing to nextController I have to stop that animation loop and after coming back I need to start it again.
UIView doesn't get
viewWillAppear
viewDidDisappear
etc
ViewController in which it's contained, however, does, so, in order to pass it to UIView you are to implement following method:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[self.view.subviews objectAtIndex:0] viewWIllAppear]; // i assume your subview is the only one, otherwise you need to know the index, or have it as an ivar/property
}
Another idea - since you use your view a lot, i assume you do not recreate it. Let it be a property of your [[UIApplication sharedApplication] delegate]. Now you can access it like this:
#define SharedView [(appDelegate*)[[UIApplication sharedApplication] delegate] sharedView];
Then make custom UIViewController and overwrite viewWillAppear:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if ( [SharedView.superview isEqual:self.view] )
{
[SharedView viewWillAppear];
}
}
You answered it yourself.
viewWillAppear
Have you looked at: UIView
Observing View-Related Changes
– didAddSubview:
– willRemoveSubview:
– willMoveToSuperview:
– didMoveToSuperview
– willMoveToWindow:
– didMoveToWindow
I have a UIViewController called LaunchController that is launched in my iPhone app when the app first opens:
#interface LaunchController : UIViewController<UINavigationControllerDelegate, UIImagePickerControllerDelegate>
Then, when a button is clicked, I push another view controller:
MainController *c = [[MainController alloc] initWithImage:image];
[self presentModalViewController:c animated:NO];
MainController has the following constructor, which I use:
- (id)initWithImage:(UIImage *)img
{
self = [super init];
if (self) {
image = img;
NSLog(#"inited the image");
}
return self;
}
and then it has a viewDidLoad method as follows:
- (void)viewDidLoad
{
NSLog(#"calling view did load");
[super viewDidLoad];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
[self.view addSubview:imageView];
NSLog(#"displaying main controller");
}
When the program runs, I see that the constructor for MainController is called (due to the output of NSLog), however viewDidLoad never gets called, even though I am calling presentModalViewController. Why is this? Why isn't viewDidLoad being called?
I think it is something as followings. When you need the property of view inside UIViewController, it will be loaded with lazy manner.
- (UIView *)view
{
if (_view == nil) {
[self loadView]; //< or, the view is loaded from xib, or something else.
[self viewDidLoad];
}
return _view;
}
After the view initialized, it will call viewDidLoad to inform the UIViewController.
You aren't loading your view controller from a xib file, and from comments you don't have anything in loadView (which is where you would create your view controller's view if you were not using a xib file).
Therefore, your view isn't being loaded, so viewDidLoad is never called.
Typically you would use initWithNibName: to initialise a new view controller, and then set the image after it (so expose the image as a property).
viewDidLoad will be called as soon as your controller's view property is accessed, that is when you display it for the first time or request it (e.g. have some code that calls c.view.
The reason viewDidLoad is not being called is because you aren't loading a view.
In your init method:
self = [super init];
means that you are just creating a naked view from scratch. not loading one from a nib.
try this instead:
self = [super initWithNibName:nil bundle:nil];
If you have a xib or nib file with the same name as the view controller class it should find if. Otherwise, you can just give a nibName that works.
UPDATE:
If you are not using nib files, then the appropriate method is NOT viewDidLoad. You have to implement loadView instead of viewDidLoad.
In your specific case, just put everything that is currently in viewDidLoad into loadView.
I'm having a problem with three20 that I'm hopeful someone will be able to help me out with.
I have a TTTableViewController that I use very similarly to how the TTTwitter app in three20's sample projects uses it. I have just three methods that I'm implementing: (id)init, (void)createModel, and (id<UITableViewDelegate>)createDelegate. And I've subclassed TTListDataSource and TTURLRequestModel for my data. To summarize, it's a fairly simple use of TTTableViewController, I'm not doing anything out of the ordinary.
When I add this TTTableViewController to a descendant of UIView, it works just fine. It loads and displays the data perfectly. For example, the following two work fine:
FooTableViewController *controller = [[FooTableViewController alloc] init];
controller.view.frame = CGRectMake(288, 20, 480, 1004);
[self.window addSubview:controller.view];
As does this:
FooTableViewController *controller = [[FooTableViewController alloc] init];
controller.view.frame = CGRectMake(288, 20, 480, 1004);
UIScrollView *scrollView = [[UIScrollView alloc] init];
scrollView.frame = CGRectMake(0, 0, 768, 1024);
// a bunch of scrollView variable initializations..
[scrollView addSubview:controller.view];
[self.window addSubview:scrollView];
The problem arises when I try to add FooTableViewController (which, again, is a subclass of TTTableViewController) to the view of a descendant of UIViewController. The following, for example, doesn't work:
FooTableViewController *controller = [[FooTableViewController alloc] init];
controller.view.frame = CGRectMake(288, 20, 480, 1004);
UIViewController *viewController = [[UIViewController alloc] init];
viewController.view.frame = CGRectMake(0, 20, 768, 1004);
[viewController.view addSubview:controller.view];
[self.window addSubview:viewController.view];
Any idea why this happens? Like I said, it works just fine when I add it to a UIView (that is, one that's not in a UIViewController), but doesn't when I try to add it to a UIViewController. Besides trying to add it like I did above, I also tried subclassing UIViewController and adding it from within. No luck.
Thanks!
EDIT I should be a little more clear on what I mean by "it doesn't work." All I see is an empty table -- just empty rows. Putting a breakpoint on createModel indeed shows that that method is not being called. Thanks!
UPDATE diwup totally pointed me towards the right solution. He was right in that it is because TTTableViewController's viewWillAppear: and viewDidAppear: weren't getting called. I verified this by subclassing UIViewController (I called it FooViewController) and adding the TTTableViewController to its view from within the class (I called the TTTableViewController variable controller). I also overrode two methods like this:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[controller viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[controller viewDidAppear:animated];
}
And, lo and behold, it worked! Of course, this isn't a long-term solution, I still want to figure out how to get viewWillAppear: and viewDidAppear: called by itself.
UPDATE2 I decided to just override viewDidLoad: like so:
- (void)viewDidLoad {
[super viewDidLoad];
[super viewWillAppear:NO];
[super viewDidAppear:NO];
}
I'm not too pleased with it, it seems hacky (and I should probably make sure viewWillAppear: and viewDidAppear: don't get called twice), but I'm ready to call it a day with it.
My answer may not be relevant. But I suspect that the problem may have something to do with the addSubview: method. Since addSubview: doesn't guarantee the view is on the top level of the view hierarchy, certain methods of that view may not get fired during or after addSubview:. These methods include viewWillAppear:, viewDidAppear: etc etc.
Therefore, if Three20's code relies on those interface methods, things could go wrong. I would suggest you try to present that controller modally and see what will happen.
The same question.
Just call the instace of TTTableViewController ;
for example:
TTTableViewController tableViewController;
[tableViewController createModel]
and
[tableViewController updateView]
in viewDidLoad.
it's works.
If I have a UIView, called " someView", than, I have a controller, which is called "myController".
I want to assign the someView with myController, how can I do so in code? Thank you.
Basically:
Read what #Lou Franco suggests.
Implement the load view like that:
- (void)loadView {
[super loadView];
MyCustomView *view = [[MyCustomView alloc] initWithFrame:self.view.frame];
self.view = view;
[view release];
// Setup other views if needed
}
From:
http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html
If you specify the views manually, you must implement the loadView method and use it to assign a root view object to the view property.
Read about loadView here:
http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html#//apple_ref/occ/instm/UIViewController/loadView