In my app, you can add a photo using a modal view. When the modal view gets dismissed, I want to automatically switch the tab bar controller to the second tab (the photo viewer screen).
I found this answer about how to programmatically switch tabs, but I'm not sure where to put this code in the modal view controller.
You can create a delegate protocol and assign a delegate property to the viewController being presented modally, and make it inform its delegate when it's about to call dismissModalViewControllerAnimated after taking a picture.
edit: added some more information about implementation
On the view controller class you are presenting modally, you would declare a protocol:
#protocol YourUIViewControllerSubclassDelegate;
Then, you would add a property to your class:
#property (nonatomic, unsafe_unretained)id <YourUIViewControllerSubclassDelegate>delegate;
finally, after your call the #end on your class interface declaration, you would complete the protocol:
#protocol YourUIViewControllerSubclassDelegate <NSObject>
- (void)viewController:(YourViewControllerSubclass *)viewController isBeingDismissedWithImage:(BOOL)imageTaken;
#end
So, inside your YourUIViewControllerSubclass, before calling dismissModalViewControllerAnimated, you would do:
[self.delegate viewController:self isBeingDismissedWithImage:YES or NO];
So, when you create YourUIViewControllerSubclass, you need to assign the delegate property. Whoever is the delegate of YourUIViewControllerSubclass needs to conform to the YourUIViewControllerSubclassDelegate protocol, and implement the protocol method. Inside this implementation of the protocol method, you would switch to whatever tab you would like to switch to.
Related
Please have a look at the screenshot of my project for better understanding
I have browsed a lot in stack overflow and other sites regarding writing custom delegates. But in my case the delegate is not getting called. As can be seen in the screenshot, the initial view controller has a button on click of which the tab bar gets called. From the first Tab bar screen, suppose I want to pass the data back to the initial view controller, how do I do? I can even use NSUserDefaults but I want to code the right way. So I came to know that delegates are best way to pass data back from one controller to the previous controller. But since I am using tab bars in between, the delegate is not getting called.. Kindly help,
Following is the code,
I want data to be passed from first tab to the initial controller.
TabScreenController.h:
#protocol TabScreenControllerDelegate <NSObject>
-(void)someFunction:(NSString*)someValue;
#end
#interface TabScreenController : UIViewController
#property (nonatomic, weak) id <TabScreenControllerDelegate> delegate;
#end
InitialViewController.h:
#interface InitialViewController : UIViewController<TabScreenControllerDelegate>
InitialViewController.m:
TabScreenController* controller = [[TabScreenController alloc]init];
[controller setDelegate:self];
//The delegate is not getting called
-(void)someFunction:(NSString *)someValue{
NSLog(#"%#", someValue);
}
The delegate is not getting called perhaps the TabScreenController in InitialViewController.m is a different instance than the one that gets created on clicking the tab.
Please help me regarding this.. How do I handle such scenarios. Let me know if I have not made myself clear..
Thank you
The error is that you are not setting the delegate the existing TabScreenController but instantiating a new TabScreenController and setting the delegate. When using TabBarController all the childViewControllers are already instantiated.
In your case you need to look for TabScreenController and then set its delegate.
NSArray* tabChildViewControllers = tabBarController.viewControllers;
for (UIViewController * childVC in tabChildViewControllers) {
if ([childVC isKindOfClass:[TabScreenController class]]) {
// set your the delegate
}
}
I want to segue back from ViewControllerTwo to ViewControllerOne. I created a button that is responsible for doing that, but my problem is that the button is part of custom UIView class that is added to ViewControllerTwo, the button is not a part of the main view of ViewControllerTwo.
So in the custom UIView class I have the method that reacts if the button is clicked...
-(void)buttonClicked{
[SecondViewController performSegueWithIdentifier: "ShowFirstViewController" sender:nil];
}
When I do this I get an error: "performSegueWithIdentifier not a method of class" which makes sense.
So how can I segue between two viewcontrollers where the button responsible for the segue is not actually part of either view controller and is in a different class.
I think you can have a delegate call back to your SecondViewController and implement the performSegueWithIdentifier in the delegate callback method in SecondViewController.
It goes like this:
Above your custom UIView class interface create a protocol like this
#protocol CustomViewDelegate <NSObject>
- (void)buttonDidTap;
#end
Then create a property in your interface
#property (nonatomic, weak) id <CustomViewDelegate> delegate;
In your custom UIView *.m add this
-(void)buttonClicked{
[self.delegate buttonDidTap];
}
Conform the protocol to your SecondViewController like this
#interface SecondViewController: UIViewController <CustomViewDelegate>
set the delegate in your viewDidLoadMethod like this
-(void)viewDidLoad{
[super viewDidLoad];
self.yourCustomView.delegate = self;
}
implement this method inside the view controller .m file
- (void)buttonDidTap{
[self.performSegueWithIdentifier: "ShowFirstViewController" sender:self];
}
I'm more of a swift guy i think this should work fine.
iOS 9.3, Xcode 7.3, ARC enabled
This is what I'd do to troubleshoot:
Step 1: Make sure that you have a proper storyboard identifier for the view controllers you wish to segue between. The views simply attach to the view controllers, custom or not.
To do this, go to "*.storyboard" show the Utilities (right pane) and navigate to the Identity Inspector. Make sure you have "ShowFirstViewController" entered in the Storyboard ID field.
I have a button in mainviewcontroller, when that button is tapped I want to call a method on another view controller. Here below is an image showing my scenario, Green button click to call preview controller VC1 received method without navigation anything. I just need to call that method only!
Declare a method in .h file of VC1 and implement in .m file of VC1
Call that method from MainView Controller ,
Create a NSNotificationObserver in MainView Controller and implement it in .m file of MainView Controller ,
Now when method of VC1 is called and before it returns, fire a PostNotification from VC1 and pass the parameter which you want in MainView Controller.
#RobAu has given correct answer as you can use NSNotificationObserver and call from anywhere.
Other alternate which i have used is using protocol and is very simple.
Just declare a protocol in the child controller. while launching the view put the parent controller as delegate. now call the delegate method from where ever you want from child controller
Here is example which i used (In my case all the child controller was of same kind)
//ChildClass.h file of child class
#protocol updateIndex <NSObject>
-(void)updateMediaId:(NSString*)currentMediaId;
#end
#interface ChildClass : UIViewController
#property NSString *imageID;
#property id updateIndexDelegate;
#end
//ChildClass.m file for child class where you want to call the delegate method
(I called in viewDidAppear method)
-(void)viewDidAppear:(BOOL)animated{
[self.updateIndexDelegate updateMediaId:_imageID];
}
And in ParentClass.m file of parent class use the delegate to self like this
ChildClass *childObject = [[ChildClass alloc] init];
childObject.delegate = self;
and define the delegate method like this
-(void)updateMediaId:(NSString*)currentMediaId {
NSLog(#"%#",currentMediaId);
}
Enjoy coding
I have 2 table view controllers where I on button click on first controller, I am pushing to another view controller.
On the second table view controller, I have a list of items which is checkmarked upon selection. I want to return the selected value to the first view controller.
Also, please let me know how can I use that value in first view controller.
I cant use seagues and the second view controller is generic so I cannot set any of the variables of first view controller in it.
One option would be to create a delegate for that second view controller
In the .h you could declare
#protocol SecondControllerDelegate <NSObject>
- (void)selectionDidFinish:(NSArray*)objects;
#end
#interface SecondViewController : UIViewController
#property(nonatomic, weak) id<SecondControllerDelegate> delegate;
Then in your .m in view will disappear :
- (void)viewWillDisappear:(BOOL)animated{
[self.delegate selectionDidFinish:yourArray];
}
And in your first view controller you'd have to implement this protocol :
in .h :
#interface FirstViewController : UIViewController <SecondControllerDelegate>
and in .m
- (void)selectionDidFinish:(NSArray*)objects{
//Do whatever you want with selected objects
}
and of course when you create your second view controller you'd have to do :
SecondViewController *sVC = [[SecondViewController alloc] init];
sVC.delegate = self;
[self.navigationController pushViewController:sVC animated:YES];
A possible solution is to create a mutable object (NSMutableArray, NSMutableDictionary) in the parent controller and pass it to the child, so the child can modify it and when you are back to the parent - the mutable object will contain the modified values.
Another approach, which requires a little more knowledge is to use a protocol. The basic idea is to create a protocol and a delegate, so the child can "notify" the parent that it chose some values. You can check these examples:
http://www.theappcodeblog.com/2011/04/15/passing-data-between-views-tutorial-using-a-protocol-delegate-in-your-iphone-app/
http://iosdevelopertips.com/objective-c/the-basics-of-protocols-and-delegates.html
Please tell me if you need more information.
You can create delegates. Checkout the following link:
http://www.hardcodedstudios.com/home/ryan-newsome/simpledelegatetutorialforiosdevelopment
I got an app with my custom TabBar Controller Class.
I tried to implement tabbar controller delegate method:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
NSLog(#"%i",tabBarController.selectedIndex);
}
But it doesnt work. Why?
in ViewDidLoad i write:
self.tabBarController.delegate = self;
And in .h i implement:
#interface BaseViewController : UITabBarController <UITabBarControllerDelegate>
In your custom TabBarController, do not use
self.tabBarController.delegate = self;
But use
self.delegate = self;
.tabBarController returns the nearest ancestor in the view controller hierarchy that is a tab bar controller, but your custom TabBarController IS the controller you want to target, so no need to search in its hierarchy
You have said, that it's your custom TabBarController. What is the customisation you've done? If you changed the TabBar panel and replaced it with your own to use
setSelectedIndex:
setSelectedViewController:
methods manually, then you should call delegate's methods manually too.
According to the Apple's documentation:
There are two types of user-initiated changes that can occur on a tab
bar:
The user can select a tab.
The user can rearrange the tabs.
Both types
of changes are reported to the tab bar controller’s delegate, which is
an object that conforms to the UITabBarControllerDelegate protocol.
Also check the UITabBarControllerDelegate Protocol Reference
In iOS v3.0 and later, the tab bar controller calls this method regardless of whether the > selected view controller changed. In addition, it is called only in response to user taps in > the tab bar and is not called when your code changes the tab bar contents programmatically.
Delegate will respond only if user interacts with its UITabBar control.