Tab bar, reload every time tab is pressed - objective-c

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()
}

Related

Instance variables not working in ViewController in UINavigationController

I'm still new to iOS development but I've ran into a problem that I can't solve and I've tried looking online but can't find anything yet.
I'm using a UIImagePickerController to pick and image and I'm using it in the App Delegate. When an image is returned, in the imagePickerController:didFinishPickingMediaWithInfo method, I want to make a new navigation controller with a view controller and put it over the "app".
Here is how I'm doing it:
CustomNavigationController *customNavigationController = [[CustomNavigationController alloc] init];
PhotoViewController *photoViewController = [[PhotoViewController alloc] initWithNibName:#"PhotoViewController" bundle:[NSBundle mainBundle]];
[customNavigationController pushViewController:photoViewController animated:NO];
[customNavigationController.view setFrame:[[UIScreen mainScreen] applicationFrame]];
[photoViewController release];
[self.window addSubview:customNavigationController.view];
//Call method of photoViewController.
[[customNavigationController.viewControllers objectAtIndex:0] addPhotoFromData:info];
[self.tabBarController dismissViewControllerAnimated:YES completion:nil]; //Get rid of UIImagePickerController
However in the photoViewController, I don't have access to any instance variables synthesized and loaded in viewDidLoad. They all return to null. There is also a tableView and calls to reload the tableView do not actually cause the tableView to respond.
Here is some of the code from photoViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.photoCount = 0;
self.timestamp = [[NSDate date] timeIntervalSince1970];
self.photos = [[NSMutableArray alloc] initWithCapacity:5];
self.photosData = [[NSMutableArray alloc] initWithCapacity:5];
self.uploadingCount = 0;
UINib *customCell = [UINib nibWithNibName:#"CustomTableCell" bundle:[NSBundle mainBundle]];
[self.tableView registerNib:customCell forCellReuseIdentifier:#"customCell"];
self.tableView.separatorColor = [UIColor clearColor];
NSLog(#"%#", self);
}
and also the addPhotoFromData method:
- (void)addPhotoFromData:(NSDictionary *)info
{
[self.photos addObject:info];
NSLog(#"%#", self.photos); //Doesn't add "info" and does not return anything when later called from other methods.
[self.tableView reloadData]; //Doesn't work
Everything was working before I add in the UINavigationController. I'm completely lost.
EDIT: After some more debugging attempts, I have discovered that the view is not loaded when addPhotoFromData is called. viewDidLoad is called afterwords. Is there a way to delay method calls?
Any reason you can't have the PhotoViewController call addPhotoFromData: inside the viewDidLoad method? You can always access properties of the app delegate from the view controller:
YourAppDelegateType * delegate = [UIApplication sharedApplication].delegate;
[self addPhotoFromData:delegate.info];

NavigationBar not displaying properling when pushViewController

The problem is pretty simple to understand with pictures.
I have a UINavigationController that allow the user to switch between to views.
The first view contains a search bar and a table view like so :
The second is a basic view where information about the cell are display
When I click on the search bar, the navigation controller gets hidden and the search bar is now at the top.
Now, if I click on a cell, it goes to the second views, but the navigation bar is first hidden like below :
And then, it automatically appears like that :
I have tried a couple of things like show the navigation bar before pushing the next view controller but it is quite ugly..
Does anyone know how to have the show the navigation bar directly on the second view (like in the contact application)?
[UPDATE] : Code
AppDelegate.m (I'm talking about navigationcontroller2)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
FirstViewController *viewController1 = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
SecondViewController *viewController2 = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
viewController1.managedObjectContext = [self managedObjectContext];
viewController2.managedObjectContext = [self managedObjectContext];
viewController1.viewController2 = viewController2;
UINavigationController *navigationcontroller1 = [[UINavigationController alloc] initWithRootViewController:viewController1];
[navigationcontroller1.navigationBar setTintColor:[UIColor lightGrayColor]];
UINavigationController *navigationcontroller2 = [[UINavigationController alloc] initWithRootViewController:viewController2];
[navigationcontroller2.navigationBar setTintColor:[UIColor lightGrayColor]];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:navigationcontroller1, navigationcontroller2, nil];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
FirstView.m
- (void) searchBarTextDidBeginEditing:(UISearchBar *)theSearchBar {
[self.navigationController setNavigationBarHidden:YES animated:YES];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (!noResultsToDisplay) {
PinDetailsViewController *pinDetailsViewController = [[PinDetailsViewController alloc] initWithNibName:#"PinDetailsViewController" bundle:nil];
NSManagedObject *managedObject = [fetchedResultsController objectAtIndexPath:indexPath];
Pin *pin = (Pin *) managedObject;
[self.navigationItem setTitle:#"Pins"];
[self.navigationController pushViewController:pinDetailsViewController animated:YES];
[pinDetailsViewController updateWithPin:pin];
}
}
If you need anything else, just ask but I think it's all there.
Try to use this code in each viewcontroller.
- (void) viewWillAppear:(BOOL)animated
{
[self.navigationController setNavigationBarHidden:NO animated:animated];
}
- (void) viewWillDisappear:(BOOL)animated
{
[self.navigationController setNavigationBarHidden:YES animated:animated];
}
Before you push the new view controller, you should unhide the navigation bar:
[self.navigationController setNavigationBarHidden:NO animated:YES];
I had a similar problem with the position of my navbar. Mine was moving up behind the status bar, and I fixed the issue by manually setting the navbar frame:
-(void)adjustNavBarOrigin
{
CGRect r = self.navigationController.navigationBar.frame;
r.origin = CGPointMake(0, 20); // 20 is the height of the status bar
self.navigationController.navigationBar.frame = r;
}
I had to call this method in a number of places, including viewWillAppear: and didRotateFromInterfaceOrientation:, but it worked a treat :)
Hiding the UINavigationBar can disturb the properties sometimes. Try using the property alpha instead of hidden.

UITabBarController with a UIPopOverController with Multiple Views

I am working on a small app, according to the requirement the app should have a tabBarItem with 3 items. For this I have programmatically created the tabBarController in the AppDelegate.m file and added the 3 different viewControllers, instantiated them and everything is working good. I see the tabBarItems and all views are working. In one of the views lets say in SecondViewController I show a popOverController where I used a UITableView and populate it with items. When I click one of the items it should show another view lets say sendFeedback. Until there everything is working fine, but as soon as this sendFeedback is presented as the modal view, it occupies the whole app i.e it hides the tabBarItem.
I present the important pieces of code here for review:
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
UIViewController *viewController1 = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
viewController1.title = #"First";
UIViewController *viewController2 = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
viewController2.title = #"Second";
UITableViewController *tableView3 = [[tableViewController alloc]initWithNibName:#"tableViewController" bundle:nil];
tableView3.title = #"Third";
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2, tableView3 ,nil];
self.tabBarController.delegate = self;
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
[viewController1 release];
[viewController2 release];
[tableView3 release];
return YES;
}
In my popOverViewController.m file I am checking which row is selected in the table according to that I present the view
#pragma mark - TableView Delegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
sendFeedback *sendEmailViewController = [[sendFeedback alloc]initWithNibName:#"sendFeedback" bundle:nil];
downLoad *downloadFilelViewController = [[downLoad alloc]initWithNibName:#"downLoad" bundle:nil];
if (indexPath.row == 0)
[self presentModalViewController:sendEmailViewController animated:YES];
else
[self presentModalViewController:downloadFilelViewController animated:YES];
}
Can anyone guide me how to overcome this with the multiple views. In case if anyone requires more information from my side I would be glad to provide.
NOTE: It is the same with the other view (downLoad) as well
EDIT: Here is how I am initializing my PopOverController in the AppDelegate.m file
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
if([viewController isKindOfClass:[SecondViewController class]]){
NSInteger index = [[self tabBarController] selectedIndex];
CGRect buttonFrame = [[[[[self tabBarController] tabBar] subviews] objectAtIndex:index+1] frame];
PopOverViewController *popoverView = [PopOverViewController new];
popoverView.contentSizeForViewInPopover = CGSizeMake(250, 85);
popover = [[UIPopoverController alloc]initWithContentViewController:popoverView];
NSLog(#"X:%f Y:%f",buttonFrame.origin.x,buttonFrame.origin.y);
[popover presentPopoverFromRect:buttonFrame inView:self.tabBarController.tabBar permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
}
Thanks
Modal view controllers are used to "block" your application and fulfill a task before you can proceed. So modal view controllers are not what you want to use.
Instead wrap your controllers which have to be shown in the popover in a navigation controller. In the tableView:didSelectRowAtIndexPath: method you can push the corresponding view controller to the navigation stack.
To slove your problem:
At the place where you create the popovercontroller initialize it with a new UINavigationController. And the navigation controller you have to initialize with a rootviewcontroller namely PopOverViewController.m.
PopOverController *popoverContentController = [[PopOverController alloc] init];
UINavigationController *navcon = [[UINavigationController alloc] initWithRootViewController:popoverContentController];
popoverController = [[UIPopoverController alloc] initWithContentViewController:popoverContentController];
And in PopOverController.m
if (indexPath.row == 0)
[self.navigationController pushViewController:sendEmailViewController animated:YES];
else
[self.navigationController pushViewController:downloadFilelViewController animated:YES];

pushViewController not working with tab bar controller

I am trying to push in a new view controller with the code:
[self.navigationController pushViewController:webViewController animated:YES];
But its not working. This code happens when you select a cell in my table view. I have a table view which I think is preventing this from happening. I have tried presenting it modally but that gets rid of the navigation bar and i can't go back. There is an extremely similar to this but the answer didn't work for me!
UPDATE
- (void)loadView {
// Create an instance of UIWebView as large as the screen
CGRect screenFrame = [[UIScreen mainScreen] applicationFrame];
UIWebView *wv = [[UIWebView alloc] initWithFrame:screenFrame];
// Tell web view to scale web content to fit within bounds of webview
[wv setScalesPageToFit:YES];
[self setView:wv];
[wv release];
}
puts the web view as the WebViewController's view
there is no nib as shown above
the didSelect cell method IS CALLED using an NSLog to find out
Everything is initialized and allocated and non-zero
UPDATE:
my did select cell method:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Push the web view controller onto the navigaton stack - this implicity
// creates the web view controller's view the first time through
NSLog(#"TOUCHED!");
webViewController = [[WebViewController alloc] init];
if (webViewController == nil) {
NSLog(#"webViewController in nil state");
}
[self.navigationController pushViewController:webViewController animated:YES];
// Grab the selected item
RSSItem *entry = [[channel items] objectAtIndex:[indexPath row]];
// Construct a URL with the link string of the item
NSURL *url = [NSURL URLWithString:[entry link]];
// Construct a request object with that URL
NSURLRequest *req = [NSURLRequest requestWithURL:url];
// Load the request into the web view
[[webViewController webView] loadRequest:req];
// Set the title of the web view controller's navigation item
[[webViewController navigationItem] setTitle:[entry title]];
}
ALL OF THIS WORKED BEFORE INSERTING TAB BAR CONTROLLER
UPDATE
Where I create the controllers (IN APP DELEGATE):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
ListViewController *lvc = [[ListViewController alloc] initWithStyle:UITableViewStylePlain];
[lvc autorelease];
// Create the tabBarController
UITabBarController *tabBarController = [[UITabBarController alloc] init];
// Create two view controllers
UIViewController *vc1 = [[ListViewController alloc] initWithStyle:UITableViewStyleGrouped];
UIViewController *vc2 = [[YoutubeViewController alloc] init];
// Make an array containing the two view controllers
NSArray *viewControllers = [NSArray arrayWithObjects:vc1, vc2, nil];
// The viewControllers array retains vc1 and vc2, we can release
// our ownership of them in this method
[vc1 release];
[vc2 release];
// Attach them to the tab bar controller
[tabBarController setViewControllers:viewControllers];
// Put the tabBarController's view on the window
[[self window] setRootViewController:tabBarController];
// The window retains tabBarController, we can release our reference
[tabBarController release];
// Show the window
[[self window] makeKeyAndVisible];
return YES;
}
So I really have no idea whats going on here. Also IF YOU COULD PLEASE HELP ME WITH ANOTHER QUESTION! Go to my profile and see the question about how to stop cutoffs/add extra line for text label in uitableviewcell
I don't see the initial UINavigationViewController in your app delegate. In order to use the self.navigationController pushViewController, the view controller needs to be in one of the self.navigationController.viewControllers. Can you modify your code and try the following and see it works for you.
// Create two view controllers
UIViewController *vc1 = [[ListViewController alloc] initWithStyle:UITableViewStyleGrouped];
UIViewController *vc2 = [[YoutubeViewController alloc] init];
// Create the UINavigationController and put the list view controller as the root view controller
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:vc1];
// Make an array containing the two view controllers and the UINavigationController which has the ListViewController is the first one.
NSArray *viewControllers = [NSArray arrayWithObjects:navController, vc2, nil];
// The viewControllers array retains vc1 and vc2, we can release
// our ownership of them in this method
[vc1 release];
[vc2 release];
[navController release];
// Attach them to the tab bar controller
[tabBarController setViewControllers:viewControllers];
There are several points you have to check, in order to make the push successful.
First, the view controller to be pushed is probably designed and stored in a NIB file. Check how you create it in your code, particularly the NIB file name (assuming you use -(id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle). It must be the real NIB filename without the NIB/XIB extension.
Second, is the selection event triggered and the message really sent to the table view delegate ? You could put some logging to ensure that. The table view won't prevent the view controller from being pushed on the navigation stack.
The question isn't really precise on how/where you create that controller, so finally, if none of this works, make the test to alloc/init the controller just before pushing. You might have a better understanding of what is going on.
If the view controller is under the "More" button, then things change a bit.
Here's what worked for me to figure out what navigation controller to use:
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notif {
UITabBarController *tabBar = (UITabBarController*) self.window.rootViewController;
UINavigationController* navigationController = (UINavigationController*)self.tabBarController.selectedViewController;
UIViewController* top = nil;
if ([navigationController respondsToSelector:#selector(topViewController)]) {
top = navigationController.topViewController;
}
// the actual current navigation controller depends on whether we are on a view under the More tab
UINavigationController *curNavController;
if (top == nil) { // this implies a view under the More tab
curNavController = tabBar.moreNavigationController;
} else {
curNavController = navigationController;
}
[[LocalNotificationMgr Get] ReceivedNotification:notif navController:curNavController];
}
Basically if the user is on a view under the More tab, the actual current UINavigationController you want to use to push a UIViewController onto is the UITabBarController's moreNavigationController property.
If on a view actually visible on the tab bar itself, use the UITabBarController's selectedViewController property.
NOTE: if you're on the "More screen" itself, you can use either property.
Did you do it in the manner like below??
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(reqList==Nil)
{
reqList = [[RequestList alloc]initWithNibName:#"RequestList" bundle:nil];
}
[self.navigationController pushViewController:reqList animated:YES];
}

How to trigger navigationController:willShowViewController delegate method in AppDelegate

How can I trigger the navigationController:willShowViewController delegate method for my implementation below so that all the view controllers in the navigation controller will conform to the colorWithHexString #faf6f5?
Currently, my FirstViewController will be displayed but it doesn't seem to call the delegate method to change the color of it's navigation bar (as well as for all other view controllers that are stacked onto the navigation controller subsequently). Note that I have already added the "UINavigationControllerDelegate" to my app delegate header file.
//In App Delegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//Set First View
FirstViewController *firstView = [[FirstViewController alloc]init];
// pushes a nav con
UINavigationController *tempNavcon = [[UINavigationController alloc]initWithRootViewController:firstView];
self.navcon = tempNavcon;
[self.window addSubview:navcon.view];
}
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
navigationController.navigationBar.tintColor = [UIColor colorWithHexString:#"#faf6f5"];
}
is there a reason why you are trying to change the tintColor in an event method rather than when the UINavigationBar instance is created?
Here's how you do it. (Note that UIColor doesn't accept hex values; you should use an RGB value, or check this page.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//Initialize your view controller.
FirstViewController * firstView = [[FirstViewController alloc] init];
// Create an instance of a UINavigationController. Its stack contains only firstView.
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:firstView];
//Here is where you set the color of the navigationBar. See my note above for using RGB.
navController.navigationBar.tintColor = [UIColor greenColor];
// You can now release the firstView here, navController will retain it
[firstView release];
// Place navigation controller's view in the window hierarchy
[[self window] setRootViewController:navController];
[navController release];
[self.window makeKeyAndVisible];
return YES;
}