I have an IOS app with a UITabBar and have its delegate set to my class.. the didSelectTabBarItem properly fires and all is right with the world. However I do have some conditional code that has to occur when the UITabBarItem selected is after one particular UITabBarItem IE.. if the user clicks on tab bar item 3, and they were currently on tab bar item 2 I have to do a little extra code, that I would not have to do if the user selected tab bar item 3 and was previously on tab bar item 1.
So, is there anyway programmatically (other than keeping direct track via my program via a state variable, to know what was the previously selected item was on a tab bar when a new tab bar item is selected?
Yes it is possible, through key-value-observing (KVO).
note This answer is in regard to a UITabBar not a UITabBarController. Tab bar controller delegates have methods you are looking for (as mentioned by rdelmar).
To start, observe your tab bar like so:
- (void)viewDidLoad{
[super viewDidLoad];
[self.tabBar addObserver:self forKeyPath:#"selectedItem" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
}
I think you can already see where I'm going based on my using both options old & new. Then simply observe the change instead of using the delegate method, like so:
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
if ([keyPath isEqualToString:#"selectedItem"] && [object isKindOfClass:[UITabBar class]]){
UITabBar *bar = (UITabBar *)object; // The object will be the bar we're observing.
// The change dictionary will contain the previous tabBarItem for the "old" key.
UITabBarItem *wasItem = [change objectForKey:NSKeyValueChangeOldKey];
NSUInteger was = [bar.items indexOfObject:wasItem];
// The same is true for the new tabBarItem but it will be under the "new" key.
UITabBarItem *isItem = [change objectForKey:NSKeyValueChangeNewKey];
NSUInteger is = [bar.items indexOfObject:isItem];
NSLog(#"was tab %i",was);
NSLog(#"is tab %i",is);
}
// handle other observings.
}
Remember to remove yourself as observer in both viewDidUnload and dealloc, since viewDidUnload may never be called.
I don't know if this can be done in a way other than what you suggested (a state variable), if you're not using a UITabBarController. If you are using a tab bar controller, then you can do this in the delegate of the tab bar controller:
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
if (viewController == [self.tabBarController.viewControllers objectAtIndex:2 && self.tabBarController.selectedIndex == 1]) {
NSLog(#"Do special programming");
}
return YES;
}
This method is called before the switch is made (unlike the UITabBar method didSelectTabBarItem), so the selected index will be the index of the tab that was active before you touched the new tab.
There may be better ideas but one way to do is by by creating a NSString object in your AppDelegate to store the name of the class of the current view controller so that you can read the string from your next view controller and check the previously selected item.
In you AppDelegate.h declare a string and synthesize it.
#property (strong, nonatomic) NSString * preSelectedViewController;
And in all your UIViewControllers which are set as items for your UITabViewController do this
in .h files
#import "AppDelegate.h"
in .m files include this in your viewWillAppear: method
AppDelegate * delegate1 =(AppDelegate *) [[UIApplication sharedApplication] delegate];
if (delegate1.preSelectedViewController ==nil)
{
delegate1.preSelectedViewController=NSStringFromClass( [self class]);
}
NSLog(#"previous %#",delegate1.preSelectedViewController);
//include 2nd_viewcontroller.h file and this if statement in your 3rd_viewcontroller(i.e. where you want to check and do your other programming)
if ([delegate1.preSelectedViewController isEqualToString:NSStringFromClass([2nd_ViewController class]) ]) {
//do your little extra code
}
delegate1.preSelectedViewController=NSStringFromClass( [self class]);
NSLog(#"present %#",delegate1.preSelectedViewController);
Guess this will work for you
Why not storing the lastSelectedIndex in an iVar and in
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
you have both values on your hands.
You might even (never tried it) use
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
so you have the currently selected view controller index view selectedIndex and then via an additional method you can find the index of the to be selected index of the viewController.
I found that this works with ReactiveCocoa:
#import <ReactiveCocoa/ReactiveCocoa.h>
// ...
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
#weakify(self);
[RACObserve(appDelegate, tabBarController.tabBar.selectedItem) subscribeNext:^(UITabBarItem *selectedTab) {
#strongify(self);
NSUInteger selectedIndex = [appDelegate.tabBarController.tabBar.items indexOfObject:selectedTab];
NSLog(#"selected index: %lu", (unsigned long)selectedIndex);
}];
Related
How to achieve this stuff below? Please give me some guidance for it. I describe my issue below.
When I tap home button and remove app from tray and while I am opening app I get the login screen. I know how to use NSUserDefaults well.
But my issue is that when I navigate 3rd or 4th viewController and I press Home Button and remove app from tray, Then whenever I open app than I want to open with last open viewController.
Also same when my app is Crashing and I am opening it again then I want to open app with last open viewController state.
So I just want to know that is that possible or not? If yes, then please guide me how to achieve this stuff.
Thank you
Yes, both cases are possible.
On crash, you can use UncaughtExceptionHandler to perform some code. In you app delegate, register you handler like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
// Other didFinishLaunchingWithOptions code
And add your handler method to the same .m file
void uncaughtExceptionHandler(NSException *exception)
{
// App crashed, save last selected tabbar index to the to the NSUserDefaults
[[NSUserDefaults standardUserDefaults] setInteger:tabBarController.selectedIndex forKey:#"LastSelectedTabbarIndex"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
While app runs, to keep track of last selected tab bar controller, use UITabBarControllerDelegate and save newly selected tabbar's index to NSUserDefaults. Short example:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
NSUInteger tabIndex = [[tabBarController viewControllers] indexOfObject:viewController];
// I have newly selected index, now save it to the NSUserDefaults
}
This code will save last selected tabbar's index to the NSUserDefaults every time tabbar's selected index changes.
Finally, when you app starts (in your didFinishLaunchingWithOptions), read last saved tabbar index from NSUserDefaults and set tabbar's selected index accordingly
self.tabBarController.selectedIndex = lastSelectedIndexFromDefaults;
Edit:
If you also need to restore UINavigationControllers controllers stack, its pretty difficult task. I give you just a quick overview what comes to my mind.
There are 2 cases:
You have custom view controllers initializers and need to pass custom object to those controllers - In this case, its almost impossible (in some reasonable time) implement this
You use only -init or -initWithNibName...: to initialize view controllers in navigation stack. You could enumerate controllers from the root UINavigationController of the tab, get their classes names using NSStringFromClass and save them to NSUserDefaults. On apps start, you would reverse procedure (initialize controllers using their names strings read from NSUserDefaults using something like this: UIViewController *vc = [[NSClassFromString(#"aa") alloc] init];).
I understand you are ok with the code part so i will just give my suggestion
on viewDidLoad of every view controller set a nsuserdefault value of the top most object on navigation array.
if their are not too many branches then you can manage the push at root view controller easily
This is not the proper answer but you can use it for Navigating view after launching.
In AppDelegate file use below codes:---
#import "NewSAppDelegate.h"
#import "NewSViewController.h"
static NewSAppDelegate *globalSelf;
#implementation NewSAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[NewSViewController alloc] initWithNibName:#"NewSViewController" bundle:nil];
self.navController=[[UINavigationController alloc] initWithRootViewController:self.viewController];
self.window.rootViewController = self.navController;
[self.window makeKeyAndVisible];
globalSelf=self;
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
return YES;
}
void uncaughtExceptionHandler(NSException *exception)
{
UIViewController *currentVC = globalSelf.navController.visibleViewController;
[[NSUserDefaults standardUserDefaults] setObject:NSStringFromClass(currentVC.class) forKey:#"lastVC"];
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
UIViewController *currentVC = self.navController.visibleViewController;
[[NSUserDefaults standardUserDefaults] setObject:NSStringFromClass(currentVC.class) forKey:#"lastVC"];
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"appDidBecomeActive" object:nil];
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
In your login viewController's init method add an observer for notification and in notification method , you can apply if conditions for viewController's name received.and push to that viewController on launching LoginView controller as:---
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(openLastVC)
name:#"appDidBecomeActive"
object:nil];
// Custom initialization
}
return self;
}
-(void)openLastVC
{
NSLog(#"val ==%#",[[NSUserDefaults standardUserDefaults] valueForKey:#"lastVC"]);
if ([[[NSUserDefaults standardUserDefaults] valueForKey:#"lastVC"] isEqualToString:#"GhachakViewController"]) {
GhachakViewController *gvc=[[GhachakViewController alloc] initWithNibName:#"GhachakViewController" bundle:nil];
[self.navigationController pushViewController:gvc animated:NO];
}
}
May this help you....
I want to keep track of the index using the UIPageViewController. Whenever I swipe I need to index++ or index--. This delegate method gets called whenever you swipe back or further:
- (void)pageViewController:(UIPageViewController *)pvc didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
// If the page did not turn
if (!completed)
{
// You do nothing because whatever page you thought
// the book was on before the gesture started is still the correct page
return;
}
// I want to check here whenever the page was swiped back or further
}
How do I check in this method if the user swiped back or further? I know there are the 2 DataSource methods "viewControllerAfterViewController" and "viewControllerBeforeViewController" but I cannot check if the page transition has completed (and I can do this in the above method) any idea how I could know if the user swiped back or further in the above method?
use protocol:
MyClass : UIViewController <UIPageViewControllerDataSource,UIPageViewControllerDelegate
declare a atributes:
#property(nonatomic) NSInteger currentIndex;
#property(nonatomic) NSInteger nextIndex;
and in the methods:
-(void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers{
NewsTableViewController *controller = [pendingViewControllers firstObject];
self.nextIndex = [self.arrViews indexOfObject:controller];
}
-(void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed{
if (completed) {
self.currentIndex = self.nextIndex;
}
self.nextIndex = 0;
}
there you will have the current page.
Thanks to Corey Floyd in enter link description here
According to the documentation there does not appear to be a way to tell whether the user has swiped the page forward or backward. The boolean 'finished' will tell you whether or not the user has completed the page turn.
A workaround:
Create an int variable and using the viewControllerAfterViewController and viewControllerBeforeViewController methods either increase or decrease the value of the variable. Use that to test whether or not they moved forward or backward.
Edit: You could use presentationIndexForPageViewController from the documentation
Edit 2: Check this link here There is a method named setViewControllers:direction:animated:completion: the direction will be either UIPageViewControllerNavigationDirectionForward or UIPageViewControllerNavigationDirectionReverse
Edit 3: Code - This is assuming you know which view controller will be called by either going forward or backward:
Create a variable on your appDelegate and a setter method:
int indexVar;
- (void)setIndex:(int)indexVar;
Then on your view controllers (forward or backward) either increase the value or decrease the value (viewDidLoad):
(AppDelegate *)[[UIApplication sharedApplication] delegate] setIndex:<whatever>];
Something along those lines. This won't be an exact way to accomplish your goal, but hopefully it will get you headed in the right direction.
I did it by creating protocols in each of my ViewController classes, with the protocol method called in the viewWillAppear method. Then in the PageViewController whenever I instantiate one of the view controllers I set its delegate to be the PageViewController.
This is the 3rd ViewController in my project(Note that I've done this in each of my view controllers)
#class ViewController3;
#protocol ViewControllerPageNumber <NSObject>
-(void)viewWillAppearMyPageNumber:(int)myPageNumber;
#end
#interface ViewController3 : UIViewController
#property (nonatomic, weak) id <ViewControllerPageNumber> delegate;
#end
and in the .m file in the viewWillAppear method
-(void)viewWillAppear:(BOOL)animated{
[self.delegate viewWillAppearMyPageNumber:3];//The 3 will be different for each ViewController
}
Next, in the PageViewController.m, whenever I instantiate a view controller I set its delegate to be self( or PageViewController). viewCons is just an array of strings with my viewControllers names.
- (UIViewController *)viewControllerAtIndex:(NSUInteger)index {
id vc = [[NSClassFromString([viewCons objectAtIndex:index]) alloc] init];
if([vc isMemberOfClass:[NSClassFromString(#"ViewController3") class]]){
ViewController3 *vc3=(ViewController3 *) vc;
vc3.delegate=self;
}else if([vc isMemberOfClass:[NSClassFromString(#"ViewController2") class]]){
ViewController2 *vc2=(ViewController2 *) vc;
vc2.delegate=self;
}else if([vc isMemberOfClass:[NSClassFromString(#"ViewController") class]]){
ViewController *vc1=(ViewController *) vc;
vc1.delegate=self;
}
return vc;
}
Finally, I'm implementing my custom delegate method, which in my case is refreshing labels' text I have set on top of the PageViewController.
-(void)viewWillAppearMyPageNumber:(int)myPageNumber{
[self refreshLabelsOnCurrentPageWithIndex:myPageNumber];
}
I think the easiest solution is to to create an own ViewController class with a property that keeps track of the currently shown index. In most of the cases I need a custom ViewController for my PageViewController anyways. In my example this is the following class.
#interface PageZoomViewController : UIViewController
#property (nonatomic) int pageIndex;
#end
Then in the viewControllerAfter/Before methods you can pass the index to the new page.
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
int nextPageIndex = ((PageZoomViewController *)viewController).pageIndex-1;
PageZoomViewController *controller = [[PageZoomViewController alloc] initWithPageViewControlParent:self andFrame:[self frameForPagingScrollView] andPageIndex:nextPageIndex];
return controller;
}
When the animation for the next page finished you can easily set the current index like this.
-(void)pageViewController:(UIPageViewController *)thePageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {
if(completed) {
index = ((PageZoomViewController *)thePageViewController.viewControllers[0]).pageIndex;
}
}
Hope this helps!
I have a UINavigationController with two ViewControllers on the stack. At a certain point in the program execution, the second view controller is visible on the screen and at that moment, I would like to replace that ViewController with another. However, it's not working. Here is my code:
UINavigationController * thisNavController = self.waitingController;
// remove the Dummy and set the new page instead
NSMutableArray * newControllers = [NSMutableArray arrayWithArray: thisNavController.viewControllers];
[newControllers replaceObjectAtIndex: ([thisNavController.viewControllers count] - 1) withObject: page];
NSLog (#"visible before: %#", [thisNavController.visibleViewController description]);
[thisNavController setViewControllers: [NSArray arrayWithArray: newControllers] animated: YES];
NSLog (#"visible after: %#", [thisNavController.visibleViewController description]);
[thisNavController.visibleViewController.view setNeedsDisplay];
The above code produces this output:
2011-05-05 13:30:22.201 myApp[3286:207] visible before: <DummyViewController: 0x4c8b4c0>
2011-05-05 13:30:22.209 myApp[3286:207] visible after: <RealViewController: 0x60173f0>
But what is shown on the screen does not change. It seems that everything works fine after I switch tabs, so it seems that it is a redrawing problem, but setNeedsDisplay does nothing and I couldn't find a method that tells the NavigationController that its viewControllers have changed.
Is there some refresh mechanism that I have to trigger to refresh the screen?
One solution would be to say add 2 (initial) view controllers when your app is started, and only allow navigation from the 2nd and 3rd ones, falling back to the 1st (root) view controller in your senario described. You never allow navigation back to this 1st view controller or from this 1st view controller to the 2nd; you see this sort of behaviour in some of Apple's apps, like iTunes and Remote - if there's no network connect the app shows a no-network connection view immediately.
So, when you want to show the 1st view controller above, you do something like:
NSArray *array = [navigationController popToRootViewControllerAnimated:NO];
Without more info about the navigation behaviour of your app I hope this helps.
Or show a modal view controller?
The problem turned out to be the fact that I was trying to replace the view controller stack before the initial transition animation for the Dummy controller has finished. This can be prevented in the following manner.
First, preserve the (eventual) delegate, set the current object as the delegate, set a flag that animation is in progress and push the new controller:
self.oldNavigationControllerDelegate = self.waitingController.navigationController.delegate;
self.waitingController.navigationController.delegate = self;
self.isAnimating = YES;
[viewController.navigationController pushViewController: [[DummyViewController alloc] init] animated: YES];
Then, implement the UIViewControllerDelegate protocol methods as follows:
#pragma mark -
#pragma mark UINavigationControllerDelegate methods
- (void) navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (navigationController == self.waitingController.navigationController)
self.isAnimating = YES;
}
- (void) navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (navigationController == self.waitingController.navigationController) {
self.isAnimating = NO;
if (self.readyPage != nil)
[self pageIsReady: self.readyPage]; // method to load the ready controller
}
}
After that, whenever your content/controller/download/whatever is ready, make sure that the navigation controller is no longer animating. If it is, set a flag that the page is ready. If it isn't, load the page:
if (self.isAnimating)
self.readyPage = controller;
else
[self pageIsReady: controller];
And, of course, implement the actual loading of the new stack (as usual):
- (void) pageIsReady: (UIViewController *) page {
// this method should replace the dummy that is spinning there
UINavigationController * thisNavController = self.waitingController.navigationController;
// remove the Dummy and set the new page instead
NSMutableArray * newControllers = [NSMutableArray arrayWithArray: thisNavController.viewControllers];
[newControllers replaceObjectAtIndex: ([thisNavController.viewControllers count] - 1) withObject: page];
thisNavController.viewControllers = [NSArray arrayWithArray: newControllers];
thisNavController.delegate = self.oldNavigationControllerDelegate; // restore the original delegate
// clean up
self.isAnimating = NO;
self.readyPage = nil;
self.waitingController = nil;
self.oldNavigationControllerDelegate = nil;
}
This makes everybody happy :P
I have a TabBarController with 2 tabs, in one is a MapView and in the other one a simple TableView in a NavigationController. Both display Data from the same source. If any Data in the table is tapped, I add a DetailViewController to the NavigationController and show more details. Now on the MapView I also want to open this DetailViewController when the Data is tapped in the map. What's the best way to do this? I tried some with Notification but this doesn't work well because the TableViewController is finished loading (and registered as an observer) after the Notification is sent.
Here's my code:
MapViewController:
- (IBAction)goToNearestEvent:(id)sender {
if (currentNearestEvent) {
[[self tabBarController] setSelectedIndex:1];
NSDictionary *noteInfo = [[NSDictionary alloc] initWithObjectsAndKeys:currentNearestEvent, #"event", nil];
NSNotification *note = [NSNotification notificationWithName:#"loadDetailViewForEvent" object:self userInfo:noteInfo];
[[NSNotificationCenter defaultCenter] postNotification:note];
[noteInfo release];
}
}
TableViewController:
- (void)viewDidLoad {
[super viewDidLoad];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:#selector(loadDetailViewForEvent:)
name:#"loadDetailViewForEvent"
object:nil];
}
- (void)loadDetailViewForEvent:(NSNotification *)note {
Event *e = [[note userInfo] objectForKey:#"event"];
[self loadEventDetailViewWithEvent:e];
}
So I'm very new to iOS / Cocoa programming. Maybe my approach is the wrong choice. So I hope anybody could tell me how to solve such things the right way.
I forgot to declare my structure clearly:
- UITabBarController
- MapView (1)
- NavigationControllerContainer
- NavigationControllerView (2)
- TableView
I want to push a new View from the MapView (1) to the NavigationControllerView (2).
If you're going to use notifications, the fix is to force the second tab to be "created" before it's displayed.
Something like:
UIViewController *otherController = [[[self tabBarController] viewControllers] objectAtIndex:1];
otherController.view; // this is magic;
// it causes Apple to load the view,
// run viewDidLoad etc,
// for the other controller
[[self tabBarController] setSelectedIndex:1];
I don't have access to my code, but I did something similar to:
[[self.tabBarController.viewControllers objectAtIndex:1] pushViewController:detailView animated:YES];
Give this a try and let me know.
I think the observer/notification pattern is the right one. However, you normally want "controllers" to observe "model" objects.
I would create a Model object that contains the selected Event.
When each viewController is loaded, it looks at the "Model" object and directs itself to the selected event.
When any of the viewControllers changes the selected event, it does so in the Model, and then the notification propagates to the other(s) controllers.
I'm switching views in the context of a navigation view heirarchy, and I want to be able to determine at switch time what the prior view was that is being pushed under the new view.
I'm trying this in a UINavigationControllerDelegate:
(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
NSLog( #"Switching from %# to %#",
NSStringFromClass( [[navigationController visibleViewController] class] ),
NSStringFromClass( [viewController class] )
);
}
I get this:
2009-08-05 20:05:21.274 App Name [85913:20b] Switching from
ManagementScreen to ManagementScreen
unfortunately it appears that before "will" is called, it is already swapped out in the state of the UINavigationController such that viewController passed in is always the same as the visibleViewController on the UINavigationController (and also the topViewController property, not demonstrated here but I tried it with the same code).
I would like to avoid extending the navigation view controller, and honestly while I can easily put a property on the delegate - however I'm wondering if this behavior is possible within the existing framework (seems will should be called before it happens where as did happens after, but it seems the state of the navigation controller is modified before either).
Thanks!
I don't think the answers that use the UINavigationControllerDelegate work because, as the question points out, by the time the delegate is called the view controller that will be displayed is already the value for navigationController.topViewController and navigationController.visibleViewController.
Instead, use observers.
Step 1. Set up an observer to watch for the UINavigationControllerWillShowViewController notification:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(viewControllerChange:) name:#"UINavigationControllerWillShowViewControllerNotification" object:self.navigationController];
Step 2. Create the notification callback (in this example called viewControllerChange) and use keys in the notifications userInfo dictionary to see the last and next view controllers:
(void)viewControllerChange:(NSNotification *)notification {
NSDictionary *userInfo = [notification userInfo];
NSLog(#"Switching from %# to %#", [[userInfo objectForKey:#"UINavigationControllerLastVisibleViewController"] class], [[userInfo objectForKey:#"UINavigationControllerNextVisibleViewController"] class]);
}
- (void)navigationController:(UINavigationController*)nc
didShowViewController:(UIViewController*)vc
animated:(BOOL)animated
{
NSLog(#"Switching from %# to %#",
NSStringFromClass([vc class]),
NSStringFromClass([[nc.viewControllers objectAtIndex:[nc.viewControllers count]-1] class]));
}