Getting Current ViewController Name in Parent ViewController - iphone

I have view controller as follows
parent view Controller
#interface Parent : UIViewController
{
}
child view Controller
#interface Child : Parent
{
}
Now i want current viewcontroller name in parent viewcontroller, I have searched but got simple clue is.
If it is a navigation based app, you can get the current view controller by,
UIViewController *currentVC = self.navigationController.visibleViewController;
But what is the currect procedure to access the current viewcontroller name in Parent Viewcontroller.

try this
for(UIViewController * view in self.navigationController.viewControllers)
{
if([view isKindOfClass:[Child class]])
{
//child VC is displayed on screen
}
}

Code below can help. I have not tried it but let me know if it worked
Write the following method in Parent class
-(void)getClassName:(NSString*)className{
NSLog(className);
//Your code here
}
Following lines where you need to access the current viewcontroller name
[self getClassName:NSStringFromClass([self class])];
Hope this post was helpful

I have founded the answer,
in Parent ViewController:
- (void)viewDidLoad
{
UIViewController *currentVC = self.navigationController.visibleViewController;
NSLog(#"The Current Class : %#", [self getClassName:currentVC]);
}
- (NSString*) getClassName:(id) obj
{
const char* className = class_getName([obj class]);
NSString *clsName = [#"" stringByAppendingFormat:#"%s",className];
return clsName;
}
When we are calling [super viewDidLoad] from Child ViewController then Parent ViewController was initialized, Here i am taking the class name of the current view controller. So In my Application i dont want to write this line of code in each view controller instead i have written in Parent View Controller.
Note: This work for navigation based app only, because we are getting current visibleViewController from navigationController

Related

add subview to a view controller from another view controller

I have two view controller classes. On the first, I have an image view and on second view controller there is a text view. The second view controller has a done-button, on clicking done-button I want to add a label on the first view controller's image and pass text view's text on that label.
Is there any way to do it?
Please suggest me.
Use delegates. Create a protocol on the Second view controller
and make the First view controller its delegate. Use delegate methods to send the textview's text as message to the delegate (or in general, send any kind of data between classes).
Keep a reference to the second view controller in the first view controller.
Call a public function in the second view controller from the first view controller.
View Controller A:
#interface ViewControllerA : UIViewController
{
#public
NString *text;
}
View Controller B:
#interface ViewControllerB : UIViewController
{
#public
ViewControllerA *refToA;
}
Code to launch view controller B from A:
ViewControllerB *vc = [[ViewControllerB alloc] initWithNibName:#"ViewControllerB" bundle:nil];
vc->refToA = self;
[self presentModalViewController:vc animated:YES];
in View Controller B set the value:
refToA->text = #"text to pass";
[refToA.view addSubview:button];
View did appear in A:
- (void)viewDidAppear:(BOOL)animated
{
if (text != nil)
{
NSLog(#"%#", text);
// create your button here
}
}

Check which viewController is running in IPhone application Programmatically in Appdelegate

Is their any Possibilty to Check which viewController is running in IPhone application Programmatically in Appdelegate
There is no easy answer to this. You need to walk the view controller hierarchy starting with the main window's root view controller. If you encounter a UINavigationController you need to look at the topViewController. Once you get to a UIViewController, you need to look at the modalViewController, if any. If you have any tab bar controllers then you need to look at the currently selected tab.
Things like UISplitViewController complicates things since this can show two view controllers at once.
Here is the start of a category method you could add to UIViewController. This only handles regular view controllers and navigation controllers.
- (UIViewController *)topMostController {
if (self.modalViewController) {
return [self.modalViewController topMostController];
} else {
if ([self isKindOfClass:[UINavigationController class]]) {
UINavigationController *nc = (UINavigationController *)self;
return [nc.topViewController topMostController];
} else {
return self;
}
}
}
Call this from your app delegate on the key window's rootViewController.
Assuming you've set the rootViewController property in your AppDelegate:
[UIApplication sharedApplication].keyWindow.rootViewController;
For view controller it is not possible to get the curent running viewcontroller name.
for that you write one following method in your app delegate file & then call getCurentViewController method in each viewcontroller view did load or view did appear if you are not allocating agin by passing self to it
-(void) getCurentViewController:(UIViewController*) vc
{
if([vc isMemberOfClass:NSClassFromString(#"vcName")])
{
//write your code here
}
else if([vc isMemberOfClass:NSClassFromString(#"vcName1")])
{
//write your code here
}
}
UIViewController *currentViewController = yourRootViewController;
while (currentViewController.presentedViewController) {
currentViewController = currentViewController.presentedViewController;
}
//currentViewController is now your top-most viewController
//I use this same snippet in my production code

Detect when Viewcontroller was Pushed

I am trying to detect when a ViewController was pushed.
So I followed the doc of Apple http://developer.apple.com/library/ios/#documentation/uikit/reference/UINavigationBarDelegate_Protocol/Reference/Reference.html , about NavegationBar delegate but I didnĀ“t figured out how to make it working successfully.
I placed on my code the following code in my ViewController but it doesn't detect it was pushing.
What I am doing wrong ?
- (void)navigationBar:(UINavigationBar *)navigationBar didPushItem:(UINavigationItem *)item, {
NSLog(#"didPushItem: %#", item);
[self showimage];
}
Not clear what you are needing to do but there are several UIViewController methods for discerning its context. There are two below and a couple more in the docs
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
BOOL pushed = [self isMovingToParentViewController];
printf("viewWillAppear %d\n", pushed);
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
BOOL popped = [self isMovingFromParentViewController];
printf("viewWillDisappear %d\n", popped);
}
You should implement UINavigationControllerDelegate for UIViewController and UINavigationController related tasks.
Here is the link to the documentation:
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UINavigationControllerDelegate_Protocol/Reference/Reference.html
The particular method you want, which would be something like "navigationController:didPushViewController:animated:", does not exist in the protocol.
However, I believe you can achieve the desired behavior using the navigationController:willShowViewController:animated:. Note that this method gets called before the View for the UIViewController is shown and after it has been pushed into the UINavigationController stack.
The -viewWillApear method is reasonable, but it gets called when the view is about to be inserted into the view hierarchy, which may or may not be what you want.
If you want more control of the push/pull progress, you can override
- (void)willMoveToParentViewController:(UIViewController *)parent {
if (nil == parent) {
// Moving to nil parent means being removed from parent
} else {
// Will be inserted as a child view controller of <parent>
}
}
- (void)didMoveToParentViewController:(UIViewController *)parent {
if (nil == parent) {
// Moving to nil parent means was just removed from parent
} else {
// Was just inserted as a child view controller of <parent>
}
}
These will be called just before and after the navigation controller pushes/pops the child view controller.
From the docs...
didMoveToParentViewController:
Called after the view controller is added or removed from a container view controller.
- (void)didMoveToParentViewController:(UIViewController *)parent
Parameters
parent
The parent view controller, or nil if there is no parent.
Discussion
Your view controller can override this method when it wants to react
to being added to a container.
and...
willMoveToParentViewController:
Called just before the view controller is added or removed from a
container view controller.
- (void)willMoveToParentViewController:(UIViewController *)parent
Parameters
parent
The parent view controller, or nil if there is no parent.
Discussion
Your view controller can override this method when it needs to know
that it has been added to a container.

Using a Delegate with a TabBarController

I have a TabBarController which is set up with multiple ViewControllers at launch. When the user clicks a button I want to send them to a different ViewController in the TabBarController, and pass data through a delegate.
I have a protocol and delegate set up. However, when do you set the delegate since all the ViewControllers are in the TabBarController
Is this possible, how can I pass data to another ViewController in the TabBar when the user clicks a button. Any ideas, I'd really like to use a delegate.
- (IBAction)sendData:(id)sender
{
[self.delegate setStringData:strData];
self.tabBarController.selectedIndex = 0;
}
Edit:
So let's say I have a TabBarController with two ViewControllers called ViewControllerOne and ViewControllerTwo.
I have ViewControllerTwo set up as the delegate and protocol. This is the ViewController that will send data to ViewControllerOne after the button is pressed. ViewControllerOne implements protocol and contains the method setStringData which should be called after the button in ViewControllerTwo is pressed.
From a UIViewController you want to change the selected tab bar index and pass data.
I suggest you add a function in you app delegate for this.
That way your UIViewController won't be tied with a UITabBar (if tomorrow you want to use a different UI idiom, you will just have to change the implementation of your function in your app delegate).
To pass data, i you could try to introspection in your function : you take the current UIViewController of the new selected tab index, verify it responds to your selector and call the function.
Edit :
Let's assume your 'just' have to change the selected tabBar index (e.g. your UIViewController will always be the same on the new tab bar index).
In your first View Controller :
- (IBAction)sendData:(id)sender
{
UIApplicationDelegate * appDelegate = [[UIApplication sharedApplication] delegate];
if ([appDelegate respondToSelector:#selector(goToFirstTabBarWithData:)])
{
[appDelegate performSelector:#selector(goToFirstTabBarWithData:) withObject: strData];
}
}
In your Appdelegate :
- (void)goToFirstTabBarWithData:(NSString *)data
{
self.tabBarController.selectedIndex = 0;
UIViewController * vc = [self.tabBarController.viewControllers objectAtIndex:0];
if ([vc respondToSelector:#selector(setStringData:)])
{
[vc performSelector:#selector(setStringData:) withObject:data];
}
}
In your second View controller (the one you will arrive on) :
- (void)setStringData:(NSString *)data
{
// Do something...
}
I found a simpler solution to my problem. Inside of ViewControllerTwo, I just create an instance of ViewControllerOne and pass it that data I need. Then I change the tabBarController index to ViewControllerOne.
For example:
// A method inside of ViewControllerTwo
ViewController *viewcontrollerOne = [ViewcontrollerOne alloc] init];
[viewcontrollerOne setStringData:str];
[viewcontrollerOne release];
self.tabBarController.selectedIndex = 0;

How to remove programmatically a tab bar item created in parent class NIB file?

Within my iPhone application I have a common tab bar with three tabs that is presented from several views after pressing a button. The approach I followed was the workflow of Tweetie application, described in Robert Conn post.
Note that the main controller is a navigation controller; the tab bar is placed in a view controller's NIB file of the navigation stack, and the effect of switching between tabs is handled in a delegate didSelectItem method.
#interface GameTabBarController : UIViewController<UITabBarDelegate> {
UITabBar *tabBar;
UITabBarItem *lastGameTabBarItem;
UITabBarItem *previousGamesTabBarItem;
UITabBarItem *myBetsTabBarItem;
NSArray *viewControllers;
UIViewController *currentViewController;
}
#implementation GameTabBarController
...
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item {
UIViewController *viewController = nil;
// Get the view controller linked to the tab bar item pressed
...
// Switch to the view
[self.currentViewController.view removeFromSuperview];
[self.view addSubview:viewController.view];
self.currentViewController = viewController;
}
...
#end
Since the views of the tab bar must be customized according to the view controller the application came from, I have made this GameTabBarController a parent class with that NIB file that have the tab bar. Then, I have created several children classes:
#interface FirstGameTabBarController : GameTabBarController {
...
}
#interface SecondGameTabBarController : GameTabBarController {
...
}
...
My problem is that in some of the children classes I would like to remove the third tab of the NIB file associated with parent class. But since there is no UITabBarController involved, I cannot follow typical approaches you can found on the web, i.e. removing the view controller of the tab bar item.
How can I do that? Is it possible to remove elements that has been previously added in a NIB file?
Thanks!!
UPDATE
The solution was so easy... I have just to replace the tab bar items, instead of the view controllers:
NSMutableArray *items = [NSMutableArray arrayWithArray:self.tabBar.items];
[items removeObjectAtIndex:2];
[self.tabBar setItems:items];
Thanks to #Praveen S for pointing me in the right direction.
The following code has the solution:
NSMutableArray *tbViewControllers = [NSMutableArray arrayWithArray:[self.tabBarController viewControllers]];
[tbViewControllers removeObjectAtIndex:2];
[self.tabBarController setViewControllers:tbViewControllers];
Swift 4
func removeTab(at index: Int) {
guard let viewControllers = self.tabBarController?.viewControllers as? NSMutableArray else { return }
viewControllers.removeObject(at: index)
self.tabBarController?.viewControllers = (viewControllers as! [UIViewController])
}
This is what it works for me for Swift 4 and 5
Create a custom UITabBarController class.
Assign the custom UITabBarController class to the view on storyboard.
Remove the UIViewController on viewDidLoad:
class TabViewController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
self.viewControllers?.remove(at: 1)
}
}
You can hold a reference to that tab bar object in your class and perform the desired actions on it.
IBOutlet <Type> name;
Connect it via Interface builder and you can perform actions, and in your case you may be thinking of removing it from superview.