viewWillAppear is not called - objective-c

I know that viewWillAppear is not called on pop/push views, but I really need that method. Here is what I try
I added UINavigationControllerDelegate and adopt
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
[viewController viewWillAppear:animated];
}
-(void)viewWillAppear
{
NSLog(#"Log");
}
but viewWillAppear is still not invoked
EDIT
AppDelegate.m
self.navigationController = [[UINavigationController alloc]init];
[self.window setRootViewController:self.navigationController];
FirstView *fview = [FirstView]alloc]init];
[self.viewController pushViewController:fview animated:YES];
FirstView.m
....
-(void)viewWillAppear
{
NSLog(#"Logged");
}
....

The clue is here:
[viewController viewWillAppear:animated];
}
-(void)viewWillAppear
You call a method that takes one parameter. But your method doesn't have one. In Objective C terms that's a completely different method.
It should look like this:
-(void)viewWillAppear:(BOOL)animated {
// blah
}

do you have navigation controller on window?
paste your appdelegate.m
my working code:
self.navController = [[[CustomNavigationController alloc] initWithRootViewController:[[[HomeViewController alloc] init] autorelease]] autorelease];
[self.window addSubview:navController.view];
[self.window makeKeyAndVisible];

Related

Container View Controller not forwarding appearance methods

I'm trying to create a container view controller to hold a UINavigationController and a custom UIViewController together on screen.
I laid it out in a test program and it works perfectly, however when I tried to implement it in my real project the appearance methods for the containing View Controllers never get called.
Working Test:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
MasterStatusViewController *master = [[MasterStatusViewController alloc] init];
[self.window setRootViewController:master];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
- (void)viewDidLoad {
[super viewDidLoad];
InventoryViewController *newInventory = [[InventoryViewController alloc] init];
self.navigation = [[UINavigationController alloc] initWithRootViewController:newInventory];
self.statusRibbon = [[StatusBarViewController alloc] initWithNibName:#"StatusBarViewController" bundle:nil];
[self addChildViewController:self.navigation];
self.navigation.view.frame = self.navigationView.frame;
[self.view addSubview:self.navigation.view];
[self.navigation didMoveToParentViewController:self];
[self addChildViewController:self.statusRibbon];
self.statusRibbon.view.frame = self.ribbonView.frame;
[self.view addSubview:self.statusRibbon.view];
[self.statusRibbon didMoveToParentViewController:self];
}
Failing Project:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
MasterViewController *master = [[MasterViewController alloc] init];
self.centerController = master;
[self.window setRootViewController:master];
[self.window makeKeyAndVisible];
return YES;
}
- (void)viewDidLoad {
[super viewDidLoad];
LoginViewController *login = [[LoginViewController alloc] init];
self.navigation = [[UINavigationController alloc] initWithRootViewController:login];
self.statusRibbon = [[StatusRibbonViewController alloc] init];
[self addChildViewController:self.navigation];
self.navigation.view.frame = self.navigationView.frame;
[self.view addSubview:self.navigation.view];
[self.navigation didMoveToParentViewController:self];
[self addChildViewController:self.statusRibbon];
self.statusRibbon.view.frame = self.ribbonView.frame;
[self.view addSubview:self.statusRibbon.view];
[self.statusRibbon didMoveToParentViewController:self];
}
The views are arranged correctly and perform as expected, except the appearance methods never get called. I'm quite perplexed. Calling the methods manually doesn't seem to be a solution, as those calls aren't going through either.
EDIT: By appearance method I mean viewWillAppear, viewDidAppear, et al.
SECOND EDIT:
~ snip ~
THIRD EDIT: Upon further inspection, I believe the reason the appearance lifecycle methods aren't being called is because they aren't being called on the container view controller either. I added
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(#"MasterViewController VIEW WILL APPEAR");
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(#"MasterViewController VIEW DID APPEAR");
}
to the masterViewController and nothing, for some reason they are never being called.
Solved it. I don't know why the master appearance methods were not being called, a few cleans of xcode seemed to solve that problem.
However, those methods still weren't being forwarded to my other view controllers. Then I came across this link and learned that you always have to forward appearance calls to them no matter what. I was able to fix it by adding:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigation beginAppearanceTransition: YES animated: animated];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.navigation endAppearanceTransition];
}
-(void) viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.navigation beginAppearanceTransition: NO animated: animated];
}
-(void) viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[self.navigation endAppearanceTransition];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
I had a similar issue where I was using the containment features of UIViewController where the appearance methods were not getting forwarded whenever I added a new child view controller to the view.
It turns out that you need to call beginAppearanceTransition:animated: before you add the sub view and endApperanceTransition when you are done. You will need to do this when you add the sub view and also when you remove it in order to trigger the appearance methods.
For your case, I'd try something like this:
self.navigation.view.frame = self.navigationView.frame;
[self addChildViewController:self.navigation];
[self.navigation didMoveToParentViewController:self]
[self.navigation beginAppearanceTransition:YES animated:NO];
[self.view addSubview:self.navigation.view];
[self.navigation endAppearanceTransition];
self.statusRibbon.view.frame = self.ribbonView.frame;
[self addChildViewController:self.statusRibbon];
[self.statusRibbon didMoveToParentViewController:self]
[self.statusRibbon beginAppearanceTransition:YES animated:NO];
[self.view addSubview:self.statusRibbon.view];
[self.statusRibbon endAppearanceTransition];
What do you mean exactly by "appearance methods"? You mean, that the view doesn't appear?
In your working example, you're loading the ribbon view from a nib file:
self.statusRibbon = [[StatusBarViewController alloc] initWithNibName:#"StatusBarViewController" bundle:nil];
while you just init it in the second code example:
self.statusRibbon = [[StatusRibbonViewController alloc] init];
The latter just creates a 'fresh' view, which may result in your perception, that it doesn't appear.

Open ViewController from different class

I want to be able to open a ViewController from a different class. So I could simply call it to open a view wherever I need it.
So I have this setup in the class that holds the code:
+ (void)openCalcView: (NSString *)nameOfView {
UIViewController *controller;
if ([nameOfView isEqualToString:#"Tax"]) {
controller = [[TAXViewController alloc]initWithNibName:#"TAXViewController" bundle:nil];
}else if ([nameOfView isEqualToString:#"Rent"]){
controller = [[RENTViewController alloc]initWithNibName:#"RENTViewController" bundle:nil];
}
controller.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:controller animated:YES completion:nil];
[controller release];
}
But [self presentViewController:controller animated:YES completion:nil]; gives me a warning:
Class method '+presentViewController:animated:completion:' not found (return type defaults to 'id')
I can call simple things like NSLog through this, from any class. But this doesn't work.
Because openCalcView is a Class method, there is no UIViewController instance (i.e. no [self presentViewController:] method).
You'll need to also pass a UIViewController to this class method, something like this:
+ (void)openCalcView: (NSString *)nameOfView fromViewController:(UIViewController *)controller {
UIViewController *newController;
if ([nameOfView isEqualToString:#"Tax"]) {
newController= [[TAXViewController alloc]initWithNibName:#"TAXViewController" bundle:nil];
}else if ([nameOfView isEqualToString:#"Rent"]){
newController= [[RENTViewController alloc]initWithNibName:#"RENTViewController" bundle:nil];
}
newController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[controller presentViewController:newController animated:YES completion:nil];
[newController release];
}
the controller parameter represents the UIViewController that is opening the new view controller

Can I use pushViewController with UISegmentedControl?

I want to use pushViewController with UIsegmentedController to push to other view and xib.
Can I do that in xcode 4 ??? If I can , Could you guide me please ?
Here is some code that I try.But won't work.
-(IBAction) segmentedControlIndexChanged:(id)sender
{
if ([sender selectedSegmentIndex] == 0)
{
BDshelveController *shelve_page = [[BDshelveController alloc] initWithNibName: #"BDshelveController" bundle:nil];
}
else if([sender selectedSegmentIndex] == 2)
{
BDlibraryController *lib_page = [[BDlibraryController alloc] initWithNibName:#"BDlibraryController" bundle:nil];
[self.navigationController pushViewController:lib_page animated:YES];
}
}
yes you can, these are the things you could check
you missed segmentedIndex=1 in your code.
you missed to call pushViewController when selected segment=0
Or it is more likely that self.NavigatonController is nil
Your segmented control has not been connected valuechange to your action
If self.navigationController is nil, it depends on how you initialize your app, if your app is navigation bar driven, then this code in your AppDelegate should resolve the issue:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:yourRootViewController]; // <-- depends if you have storyboards, xib etc...you should this already initialized
[self.window addSubview:navController.view];
[navController release]; // <-- depends if you have ARC
[self.window makeKeyAndVisible];
return YES;
}
Otherwise I suppose you can initialize it where you are, by giving self as root controller.
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self];

Tab bar, reload every time tab is pressed

I am creating an app in which I have five tabs. I need to reload each controller every time when tab is pressed.
Put the code you want to reload, in the view will appear or in view did appear of all the view.
All the best.
Example:
// AppDelegate ( and <UITabBarControllerDelegate> )
// Creation tabbar and controllers
UIViewController* myController1 = [[UIViewController alloc] init] autorelease];
UINavigationController* nav1 = [[[UINavigationController alloc] initWithRootViewController:myController1] autorelease];
UIViewController* myController2 = [[UIViewController alloc] init] autorelease];
UINavigationController* nav2 = [[[UINavigationController alloc] initWithRootViewController:myController2] autorelease];
NSArray *array = [NSArray arrayWithObjects: myController1, myController2, nil];
UITabBarController* tab = [[[UITabBarController alloc] init] autorelease];
tab.viewControllers = array;
tab.delegate = self; // <-- don't forget set delegate for TabBarController
// TabBarController Delegate methods
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController;
{
// Reload selected VC's view
[viewController.view setNeedsDisplay];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//other codes
[self.tabBarController setDelegate:self]
//other codes
}
// UITabBarControllerDelegate method.
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
if ([viewController respondsToSelector:#selector(reloadDataTemp)]) {
[(YourViewController *)viewController reloadData];
}
}
So write a method to redraw the elements on your page and call it on tab press. I will edit this post if you provide more information on the problem you are facing.
if you are you are using the uitableview use this
[tableview reloaddata];
I hope you are talking about the webview the webview should reload every time a tabbar item is navigated well just implement [webview reload] in the tab bar delegate.
Swift 5
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
let vc = self.viewControllers?[1] as? stepVC // ViewController That need to be loaded
vc?.viewDidLoad()
}

Navigate from a view to another

The main: xxxVieController
and the second: OptionViewController
in xxxView controller I have
.h
#interface iMetroAlertViewController : UIViewController {
IBOutlet UIButton *option;
}
-(IBAction) goToOption;
and
.m
#implementation iMetroAlertViewController
-(IBAction) goToOption{
NSLog(#"Works");
OptionViewController *dvController = [[OptionViewController alloc] initWithNibName:#"OptionView" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:dvController animated:YES];
[dvController release];
dvController = nil;
}
Of course a OptionViewController.xib, .m and .h are created...
When I push on the button, nothing happens (the link is done cause I have an NSLog
I don't understand why it doesn't work
It probably doesn't work because you don't have a navigation controller, so calling self.navigationController returns nil.
First you have to create the navigation controller
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
RootViewController *mainMenuVC = [[RootViewController alloc] init];
navigationController = [[UINavigationController alloc] initWithRootViewController:mainMenuVC];
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
return YES;
}