how to reloadData when tableview is in a subview of subview ViewCon - ios

I have a ViewController which, has a tableView added as a subview, that is then embedded in a UINavigationController and then added as a subView to my RootViewController in my ViewDidLoad (of the RootViewConroller).
frontController = [[UIViewController alloc] init];
frontController.view.backgroundColor = [UIColor blackColor];
[frontController.view addSubview:self.tableView];
... ///
self.navBar = [[UINavigationController alloc] initWithRootViewController:self.frontController];
//finally add the Top UIViewController
self.contentViewController = self.navBar;
/// Move to new view when cell is touched
DetailsTwo *my_detailViewController = [[DetailsTwo alloc] initWithNibName:#"DetailsTwo" bundle:[NSBundle mainBundle]];
[self.navBar pushViewController:my_detailViewController animated:YES];
My problem: How do I [tableView reloadData] the table View (When I go back to the view from the back button from navBar) ?
Why are both ViewWillAppear and ViewDidAppear not getting called (Conceptually what am I missing) ?
Hope that made sense and Thank You.

#jeffamaphone - put me on the right track: (hope this helps someone else)
//.h
#interface RootViewController : UIViewController <UINavigationControllerDelegate> {
UINavigationController *navController;
}
//.m
Then implement these two methods:
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[viewController viewWillAppear:animated];
}
- (void)navigationController:(UINavigationController *)navigationController
didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[viewController viewDidAppear:animated];
}
*****Be sure to set the root view controller as the delegate for the nav controller. Now viewWillAppear / viewDidAppear will be called whenever a controller is pushed/popped from the stack.

Related

UINavigationController hidesBarOnSwipe memory leak issue

I've got a problem with hidesBarOnSwipe property of UINavigationController.
Overview :
Link to project file
I have one controller named FirstViewController which is root view of UINavigationController.
Everything is in Main.storyboard.
FirstViewController contains UIButton action. Inside that action I instantiate a SecondViewController and push it on a navigation stack.
- (IBAction)button:(id)sender {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
[self.navigationController pushViewController:vc animated:YES];
}
Inside SecondViewController there is only an hidesBarsOnSwipe property set to YES on viewDidLoad :
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationController.hidesBarsOnSwipe = YES;
}
and dealloc gets NSLogged :
- (void)dealloc {
NSLog(#"Dealloc");
}
Problem :
When we swipe up to hide navigationBar, dealloc is never get called. Instruments shows a SecondViewController memory leak here.
When we are on SecondViewController and we just press back button - everything is fine. Dealloc gets called.
There is definitly some kind of retain cycle but i have no idea why and how to avoid this kind of situation.
Some updates and temporary solution :
There is another method to perform navigationBar hiding.
What worked for me is to use :
[self.navigationController setNavigationBarHidden:hidden animated:YES];
To achieve good results add a property in your class to keep track status of navigationBar animation :
#property (assign, nonatomic) BOOL statusBarAnimationInProgress;
Implement UIScrollViewDelegate like this :
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat yVelocity = [scrollView.panGestureRecognizer velocityInView:scrollView].y;
if (yVelocity > 0 && !self.statusBarAnimationInProgress) {
[self setNavigationBarHidden:NO];
} else if (yVelocity < 0 && !self.statusBarAnimationInProgress) {
[self setNavigationBarHidden:YES];
}
}
Set navigation bar hidden should look like :
- (void)setNavigationBarHidden:(BOOL)hidden {
[CATransaction begin];
self.statusBarAnimationInProgress = YES;
[CATransaction setCompletionBlock:^{
self.statusBarAnimationInProgress = NO;
}];
[self.navigationController setNavigationBarHidden:hidden animated:YES];
[CATransaction commit];
}
I use CATransaction to check if animation of navigation bar is completed. Any way that works. Not so easy solution but at least there is no leak :)

iOS: SWRevealViewController revealToggle is been call but doesn't do nothing

I'm trying to implement SWRevealViewController on this scenario:
From my main viewController:
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:YES];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
SWRevealViewController *SWR = [storyboard instantiateViewControllerWithIdentifier:#"SWRevealViewController"];
[self presentViewController:SWR animated:YES completion:nil];
}
From my green view controller:
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:YES];
self.reveal = [[SWRevealViewController alloc] init];
self.reveal.delegate = self;
self.menu.target = self;
self.menu.action = #selector(revealToggleAction:);
[self.view addGestureRecognizer:self.reveal.panGestureRecognizer];
NSLog(#"viewDidLoad");
}
-(void)revealToggleAction:(id)sender
{
[self.reveal revealToggle:self];
}
The revealToggle action is been call but doesn't do anything. It doesn't load the rear view controller. Any of you knows this happening or what I'm doing wrong?
Assuming that you are showing the side bar menu from right side.
First Embed your first view controller to navigation controller, then in your first view controller viewdidload() or viewDidAppear method add below mentioned code i.e.
//this is your side menu view controller.
UIViewController *sideMenuController =
[self.storyboard instantiateViewControllerWithIdentifier:#"YourSideMenuIdentifier"];
//this is the navigation controller embed to your green view controller.
UINavigationController *nc1 =
(UINavigationController *)[self.storyboard instantiateViewControllerWithIdentifier:#"YourNavigationControllerIdentifier"];
//This is your reveal view Controller.
SWRevealViewController *revealViewController =
[[SWRevealViewController alloc]initWithRightViewController:sideMenuController frontViewController:nc1];
[self.navigationController pushViewController:revealViewController animated:YES];
[self.navigationController setNavigationBarHidden:YES];
This will navigate to Controller i.e Green View Controller.
then in your green view controller viewdidload() or viewDidAppear method add below mentioned code i.e.
//GreenViewController.h file
#interface GreenViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIBarButtonItem *sideBarItem;
#end
//Your GreenViewController.m file
_sideBarItem.target = self.revealViewController;
_sideBarItem.action = #selector(rightRevealToggle:);
SWRevealViewController *revealController = [self revealViewController];
[self.view addGestureRecognizer:revealController.panGestureRecognizer];
Note: For more details, check below mentioned link
http://www.appcoda.com/ios-programming-sidebar-navigation-menu/
You need set SWRevealViewController is the initial view controller.
You are creating a new instance of SWRevealViewController.
I think if you set the self.reveal to self.revealViewController it will work.

Hide and Unhide masterView from button press of detailView

I know this question has asked by many users,But i did not found any answer related to my issue.
I'm using UISplitViewController ,my application starts with login page, so i have hidden masterView on start, after some time on DetailViewController i shown the master viewController using Delegate method.
- (BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation NS_AVAILABLE_IOS(5_0)
{
return hideMaster;
}
i have initialised hideMaster to NO ,and my ViewDidLoad() of DetailViewController is below
ViewDidLoad(){
[self.splitViewController.view setNeedsLayout];
self.splitViewController.delegate =Nil;
self.splitViewController.delegate = self;
[self.splitViewController willRotateToInterfaceOrientation:[UIApplication sharedApplication].statusBarOrientation duration:0];
[super viewDidLoad];
}
it worked fine my master is now unhide.But on the same detailViewController i have a Back Button on which i'm poping the current ViewController to last viewController and again i want to hide masterViewController my code for back button is below.
- (IBAction)back:(id)sender {
hideMaster = NO;
self.splitViewController.delegate =Nil;
self.splitViewController.delegate = self;
[self.splitViewController willRotateToInterfaceOrientation:[UIApplication sharedApplication].statusBarOrientation duration:0];
[self.navigationController popViewControllerAnimated:NO];
}
Its poping the CurrentViewController to last ViewController but its not Hiding the masterViewController
Please help me out.
#JohnD,I went through your code.you are hiding the master view controller while poping the last View controller,but the viewController to which you are navigating is still showing the master View controller.therefore your masterView is still there.
follow the steps given below.
1.make delegate of UInavigationController to that ViewController which is your last singleView controller.
2.In last single ViewController(which is delegate of UINavigationController) implement following delegate method.
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[self.splitViewController.view setNeedsLayout];
self.splitViewController.delegate =Nil;
self.splitViewController.delegate = self;
[self.splitViewController willRotateToInterfaceOrientation:[UIApplication sharedApplication].statusBarOrientation duration:0];
}
3.Now implement delegate method of UISplitViewController in side lastViewController which is given below.
- (BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation NS_AVAILABLE_IOS(5_0)
{
return hideMaster;<<===============I'm assuming hide master as a variable of shared object(Singleton).
}
4.Now change your - (IBAction)back:(id)sender method with following one.
- (IBAction)back:(id)sender {
hideMaster = Yes;
[self.navigationController popViewControllerAnimated:NO];
}
I hope this will work,if you stuck some where please let me know.
you are using UISplitViewController inside your app,since you have many views but whole app is not using UISplitViewController only one view using it.
Its better to use another approach.

click navigation tabbaritem popToRootViewController

first I Install TabBarController directly as a window’s root view controller,and hava a NavigationController in viewControllers.
when the app run, I push some new viewcontroller onto the navigation stack
than I tap navigation tabbaritem, the navigationController
poptoRootViewController
How can I crash the step 3 event or stop it pop to root?
My solution to stop auto pop to root viewcontroller:
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
UITabBarController *tbc = [[UITabBarController alloc]init];
tbc.viewControllers = [NSArray arrayWithObjects:rvc,nil];
tbc.delegate = self;}
-(BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController{
if([tabBarController selectedViewController] == viewController)
return NO;
return YES;}
if you have an anther solution,wellcome write down.
try this code in tab bar app
[self.tabBarController.navigationController popToRootViewControllerAnimated:YES];
You implement didSelectViewController method in new viewController(push to new viewController)
Import UITabBarControllerDelegate,
- (void)viewDidLoad
{
[super viewDidLoad];
self.tabBarController.delegate = self;
}
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
[self.tabBarController.navigationController popToRootViewControllerAnimated:YES];
}

Problem implementing UINavigationControllerDelegate

I may have some misunderstanding regarding the use of the UINavigationControllerDelegate protocol. Here is my situation:
I have a ViewController, let's call it, BViewController that may display a PopoverViewController. BViewController is the second ViewController in a NavigationContoller's stack, after AViewController. I need to dismiss the PopoverViewController when the user hits a button in BViewController and the app takes us back to the previous view--AViewController.
To do that, I have implemented the following in BViewController
- (void)viewWillDisappear:(BOOL)animated {
NSLog(#"BViewController will disappear");
// Check whether the popoverViewController is visible
if (self.popoverController.popoverVisible==YES) {
[self.popoverController dismissPopoverAnimated:NO];
}
}
However, that is not being called directly by the framework as BViewController is inside a NavigationController. Hence, I register a UINavigationControllerDelegate with my NavigationController and implement the following two methods:
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
// Pass the message on to the viewController in question
[viewController viewWillAppear:animated];
}
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
// Pass the message on to the viewController in question
[viewController viewWillDisappear:animated];
}
However, it seems that the passed in viewController parameter in both methods is the one that is about to be shown. I would have expected that the second method gives me access to the one that is about to disappear. So, when the user hits aforementioned button viewWillDisappear gets called on AViewController (which is about to be shown) and not on BViewController (which is about to disappear). Does that sound right? The apple documentation refers in both cases to
The view controller whose view and navigation item properties are being shown.
...which is not quite clear, I think. Thank you for some help, guys.
The two delegate method are both called for the same action (showing a view controller). The navigationController: willShowViewController:animated: is called before the new view controller is visible in the gui. The navigationController:navigationController didShowViewController:animated: is called after the new view controller is shown.
You will find this pattern in a lot of delegate protocols from apple. Unfortunately you do not have a delegate method in the NavigationViewController which tells you if the action was a pop or push.
I hook in my own protocol, which will know about the TO and FROM sides:
NavigationControllerDelegate.h:
#protocol NavigationControllerDelegate <NSObject>
#required
-(void) navigationController: (UINavigationController*) navController
willMoveFromViewController: (UIViewController*) from
toViewController: (UIViewController*) to;
#end
Instead of the regular UINavigationViewController, I then use a little helper class which keeps track of the view controllers:
NavigationHandler.h:
#interface NavigationHandler : NSObject <UINavigationControllerDelegate> {
NSMutableArray* m_viewControllers;
}
In my app delegate, I create one of these objects and set it as the delegate of the navigation controller:
...
m_navigationHandler = [[NavigationHandler alloc] init];
navigationController = [[UINavigationController alloc] initWithRootViewController: mainMenuViewController];
navigationController.delegate = m_navigationHandler;
...
And from then on its a simple case of comparing my own list of view controllers with what the navigation controller has:
NavigationHandler.m
#import "NavigationHandler.h"
#import "NavigationControllerDelegate.h"
#implementation NavigationHandler
-(id) init {
if ((self = [super init])) {
m_viewControllers = [[NSMutableArray alloc] init];
}
return self;
}
-(void) dealloc {
[m_viewControllers release];
[super dealloc];
}
- (void)navigationController:(UINavigationController *)navController
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated {
// Find out which viewControllers are disappearing and appearing
UIViewController* appearingViewController = nil;
UIViewController* disappearingViewController = nil;
if ([m_viewControllers count] < [navController.viewControllers count]) {
// pushing
if ([m_viewControllers count] > 0) {
disappearingViewController = [m_viewControllers lastObject];
}
appearingViewController = viewController;
[m_viewControllers addObject: viewController];
} else if ([m_viewControllers count] > [navController.viewControllers count]) {
// popping
disappearingViewController = [m_viewControllers lastObject];
appearingViewController = viewController;
[m_viewControllers removeLastObject];
} else {
return;
}
// Tell the view that will disappear
if (disappearingViewController != nil) {
if ([disappearingViewController conformsToProtocol: #protocol(NavigationControllerDelegate)]) {
if ([disappearingViewController respondsToSelector: #selector(navigationController:willMoveFromViewController:toViewController:)]) {
UIViewController<NavigationControllerDelegate>* vcDelegate = (UIViewController<NavigationControllerDelegate>*)disappearingViewController;
[vcDelegate navigationController: navController willMoveFromViewController: disappearingViewController toViewController: appearingViewController];
}
}
}
// Tell the view that will appear
if ([appearingViewController conformsToProtocol: #protocol(NavigationControllerDelegate)]) {
if ([appearingViewController respondsToSelector:#selector(navigationController:willMoveFromViewController:toViewController:)]) {
UIViewController<NavigationControllerDelegate>* vcDelegate = (UIViewController<NavigationControllerDelegate>*)appearingViewController;
[vcDelegate navigationController: navController willMoveFromViewController: disappearingViewController toViewController: appearingViewController];
}
}
}
#end

Resources