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
Related
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 method inside my viewController (MainViewController.m) that accepts a parameter (Let's say it changes the background color of the viewController based on the number):
-(void) methodThatDoesSomething:(int)indexNumber {}
Inside this viewController I have a UITableView, but the delegate of this table is another class (TableDelegateClass.m). So inside this class I have didSelectRowAtIndexPath.
How do I call the "methodThatDoesSomething" from didSelectRowAtIndexPath? If I do it like this:
MainViewController* mainView = [[MainViewController alloc] init];
[mainView methodThatDoesSomething:indexPath.row];
It doesn't work. As another instance of the class is created and it doesn't after the viewController that I'm currently using.
I can easily do it if the delegate of the table is the MainViewController (just with this code inside didSelectRowAtIndexPath) :
[self methodThatDoesSomething:indexPath.row]
but I want to organize better the code and have different classes, one for the table and another for the viewController containing the table.
One simple solution could be to define your own delegate protocol for -(void) methodThatDoesSomething:(int)indexNumber {} so you can set TableDelegateClass delegate to your viewController and then call [delegate methodThatDoesSomething:indexPath.row]; (after checking respondsToSelector).
You can also pass the viewController instance when you create TableDelegateClass but this is a higher coupling level than delegate.
One way to solve your problem is to create a property of type MainViewController in the delegate class and assign the controller instance to it.
But maybe this problem that you are having is an indicator that the tableView delegate should indeed be the MainViewController and not another class?
I have declared my method 'callWEBservice()' in ViewController1.m and i want to call in ViewController2.m . I have created object of ViewController1.m in ViewController2.m as:
ViewController1* mainVC = [[ViewController1 alloc] init];
Now i am trying to call that method but i am unable to do. Please help on this as I am new to iOS and I have searched some are saying to use delegates.
You need to define the method signature in your .h file -
- (void) callWebService;
and then in your .m file you define the method body:
- (void)callWebService
{
// Whatever you need to do to call the web service
}
Then in ViewController2.m you can #import "ViewController1.h"
Now you can call [mainVC callWebService];
BUT The code you have shown creates a new instance of ViewController1 - If you already have an instance of ViewController1, such as the main view in your app, then this probably isn't what you wanted - you may need to set a property in ViewController2 and store a reference to your ViewController1
e.g. in ViewController2.h
#import "ViewController1.h" // or use #class ViewController1 directive
#property (strong,nonatomic) ViewController1 *mainVC;
Then before in ViewController 1, before you present ViewController2 instance
vc2.mainVC=self;
Your invocation in ViewController2 then becomes
[self.mainVC callWebService];
At the risk of confusing you further, as a design note, it probably isn't best to have the callWebService method in a view controller. It might be more appropriate to create a singleton class for this purpose.
First of all, don't use view controllers for this purpose, create a new class to handle methods of the same kind, then use that one across your view controllers. IF you want the SAME class to be shared across your program, then create a singleton.
How to call method from one class in another (iOS)
However, if you still want to do the view controller to view controller thing, the reason its not working is because you are instantiating a new view controller, not the one you were already using.
You have to pass the reference of the first VC to the second VC. It depends on how you are presenting the second VC. If you are using the Interface Builder, then you need to use:
How to pass prepareForSegue: an object
If you are manually creating and presenting the VC, before presenting it let it know which is the first VC.
You can use delegates like this:
How do I set up a simple delegate to communicate between two view controllers?
STILL consider redesigning your usage of the view controllers.
EDIT:
2 options,
1) Singleton:
Follow this guide http://www.galloway.me.uk/tutorials/singleton-classes/
2) AppDelegate:
Instantiate an object of the class in the .m of the app delegate and assign it to a property in the .h of the App Delegate.
Then, retrieve this object.
This is an example of doing it with the motion manager from ios:
AppDelegate.h:
#property (strong,nonatomic) CMMotionManager *motionManager;
AppDelegate.m
_motionManager = [[CMMotionManager alloc] init];
ViewController1-2-etc
CMMotionManager *motionManager;
motionManager = ((AppDelegate*)[UIApplication sharedApplication].delegate).motionManager;
If you want to use methods from outside your class, you should declare them in your ViewController1.h file, not in the m, otherwise they are not visible (you could still call them using performSelector:withObject:afterDelay: but you should use the first solution)
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
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.