Call method in different controller in objective c - objective-c

I have a view controller from where I will be showing a window controller using [runmodal]. I have some textfields and button in the modal window. When i click the button i need to call a method in view controller with the collective data from window controller. How can i achieve this? Is there anything to do with custom delegate method? As I am new to Mac dev and objective c some one help me to do.

You can use the delegation pattern. You define a protocol like this:
#protocol DataProviderDelegate <NSObject>
- (NSDictionary *) retrieveData;
#end
implement this protocol in your view controller:
#interface MainViewController () <DataProviderDelegate>
#end
#implementation MainViewController {
...
- (NSDictionary *) retrieveData {
....
}
...
#end
In your window controller you define a delegate property
#interface ModalWindowController : NSWindowController
#property (nonatomic, weak) id <DataProviderDelegate> dataProviderDelegate;
#end
From the main view controller, set that property to self
modalWindow.dataProviderDelegate = self
At this point the modal window controller is able to call any method of the view controller that is defined in the DataProviderDelegate protocol - for instance:
if (self.dataProviderDelegate) {
[self.dataProviderDelegate retrieveData];
}
To dig more in the delegation pattern I suggest to google for it

You can use a delegate for this. In the ModalViewController you will have to implement a delegate that will have a method per action (textfields, buttons) :
ModalViewController.h
#class ModalViewController;
#protocol ModalViewControllerDelegate <NSObject>
- (void)modalViewControllerDelegateButtonPressed:(APPCameraOverlay *)overlay;
- (void)modalViewControllerDelegate:(APPCameraOverlay *)overlay
textFieldEdited:(NSString *)text;
#end
#interface ModalViewController : UIViewController
#property (nonatomic, weak) id <ModalViewControllerDelegate> delegate;
#end
Then, you will be able to call your delegate methods inside your ModalViewController.m :
ModalViewController.m
// The method linked to your button
- (IBAction)actionButtonPressed {
[self.delegate modalViewControllerDelegateButtonPressed:self];
}
// Your textfield method that is called when input has changed
- (void)textFieldDidEndEditing:(UITextField *)textField {
[self.delegate modalViewControllerDelegate:self
textFieldEdited:textField.text];
}
Now, you just have to set your ModalViewController delegate object in the ViewController when showing the modal controller :
ViewController.m
#import "ModalViewController.h"
// We create an extension to the class to implement the delegate protocol
#interface ViewController () <ModalViewControllerDelegate>
#end
#implementation ViewController
// This method gets called by apple when a view controller is showed (modally, pushed or embedded)
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// if the view that is showed is the ModalViewController
if ([segue.destinationViewController isKindOfClass:[ModalViewController class]]) {
ModalViewController *controller = segue.destinationViewController;
controller.delegate = self;
}
}
// You have to implement the delegate methods now :
- (void)modalViewControllerDelegateButtonPressed:(APPCameraOverlay *)overlay {
// Do whatever you want when the button is pressed on the ModalViewController
}
- (void)modalViewControllerDelegate:(APPCameraOverlay *)overlay
textFieldEdited:(NSString *)text {
// Do whatever you want when the textfield is edited
}
#end

Add the view controller as an instance variable to your (subclassed) window controller, and then when the button is clicked you can send a method to the view controller with the collective data from the window controller.

Related

UIPopoverControllerDelegate delegate methods not being called

I have a screen with a button. Clicking the button will display a popover with two buttons. I want to be able to use the following method when the popover is dismissed:
#pragma mark - UIPopoverControllerDelegate
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
NSLog(#"OrderViewController.m -popoverControllerDidDismissPopover start");
}
The popover view has its own class:
#import <UIKit/UIKit.h>
#import "MenuItemModel.h"
#interface SelectedItemsOptionsViewController : UIViewController
#property (weak) id <UIPopoverControllerDelegate> delegate;
#property (strong, nonatomic) MenuItemModel *item;
#end
The class which creates the popover has:
#interface OrderViewController : UIViewController <PageViewControllerDelegate,
UITableViewDataSource, UITableViewDelegate, ServiceConnectorDelegate,
UIPopoverControllerDelegate>
So the OrderViewController - wants to know when SelectedItemsOptionsViewController has been dismissed.
I have the method declared (first block of code) and I am setting the delegate as:
SelectedItemsOptionsViewController *destViewController = (SelectedItemsOptionsViewController *)segue.destinationViewController;
popSegue = (UIStoryboardPopoverSegue *)segue;
[destViewController setDelegate:self];
destViewController.item = toDisplay;
So I am setting the delegate OK as far as i'm aware... the delegate property is #syntheized in th SelectedItemsOptionsViewController.m and well, its driving me a bit crazy.
I could be misunderstanding something here but looks like you're assigning the delegate for a UIViewController class, but where are you assigning the popOver its delegate, in the storyboard?

How to modify the sender ViewController from the called ViewController?

I have a login view controller called from a Storyboard segue. When the user logs in correctly, I need to close the current ViewController, return to the caller ViewController and hide the login button.
How can I refer to the sender ViewController, to hide the button? Do I have to pass an instance of the root ViewController to the login or is there another way?
Use delegation.
For your DetaliViewControler create a protocol, like
#protocol DetailViewControllerDelegate <NSObject>
-(void)successFullyLoggedInOnController:(DetailViewController *) controller;
#end
add a delegate declaration to DetailViewController's interface like
#property (weak) id<DetailViewControllerDelegate> delegate;
Make the MasterViewController conform to the protocol.
-(void)successFullyLoggedInOnController:(DetailViewController *) controller
{
[self.loginButton setHidden:YES];
}
Now just before the MasterViewController displays the DetailViewController, doe something like
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"DetailViewSegue"]) {
DetailViewController *vc = segue.destinationViewController;
vc.delegate = self;
}
}
In the DetailViewController once the credential where entered and verified call
[self.delegate successFullyLoggedInOnController:self];
and dismiss the DetailViewController
You should use delegation. Make the VC with the button the other one's delegate. When log in is successful, you dismiss your VC and call the delegate method to hide the button.

Calling method to view controller delegate, won't dismiss modal view

I have the following simple view controller class set up
#protocol ThermoFluidsSelectorViewControllerDelegate;
#interface ThermoFluidsSelectorViewController : UIViewController <UITextFieldDelegate>
#property (weak, nonatomic) id <ThermoFluidsSelectorViewControllerDelegate> delegate;
// user hits done button
- (IBAction)done:(id)sender;
#end
#protocol ThermoFluidsSelectorViewControllerDelegate <NSObject>
-(void) didFinishSelection:(ThermoFluidsSelectorViewController *)controller fluidID: (NSString *)fluidID;
#end
the 'didFinishSeletion: fluidID:' method is defined in the master view controller and should dismiss the selector view controller when called. When the done button is pressed the following method is called:
- (IBAction)done:(id)sender
{
[[self delegate] didFinishSelection:self fluidID:nil];
}
the 'done:' method gets called (checked with an alert) but 'didFinishSelection...' is not getting called so the view will not revert back to the main screen. Any ideas?
It sounds like you have not assigned your delegate in your master view controller.
You should have something like this in your master view controller which sets up the delegate:
ThermoFluidsSelectorViewController *view = [[ThermoFluidsSelectorViewController alloc] init];
view.delegate = self;
here you can see I create the view, then set the delegate of the view back to myself.
If you are not creating the Thermo... view controller programatically, but have used a storyboard, then you can set the delegate in the prepareForSegue: method of your master view controller:
// Do some customisation of our new view when a table item has been selected
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure we're referring to the correct segue
if ([[segue identifier] isEqualToString:#"MySegueID"]) {
// Get reference to the destination view controller
ThermoFluidsSelectorViewController *cont = [segue destinationViewController];
// set the delegate
cont.delegate = self;
Hope this helps.

Passing delegate to a viewcontroller through a viewcontroller

I have three viewControllers in my storyboard and three viewController classes for each of them. From my main viewController, I am opening a navigation viewController in a 'modal' type segue, which is a multi step form and has two views in it. When the user hits 'Finish' on the last (which is second) view, the modal is dismissed and user is back to the main screen.
I am doing this with delegates. and the code for the finish button is also in a delegate and is placed on the main viewController's implementation file. In achieving this I passed the delegate from main view to the navigation's first view, and then from the first view on clicking 'next', I passed the delegate to the second (last) view (which has the finish button).
the passing of delegate from main to navigation's first page is like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"CreateCast"])
{
UINavigationController *navigationController = segue.destinationViewController;
CreateCastStepOneVC *createCastStepOneVC = [[navigationController viewControllers] objectAtIndex:0];
createCastStepOneVC.delegate = self;
}
}
the passing of delegate from navigation's first view to second view is like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"ToCastStepTwo"])
{
CreateCastStepTwoVC *createCastStepTwoVC =
segue.destinationViewController;
createCastStepTwoVC.delegate = delegate;
}
}
Things are done well and delegate is doing its job as required. But a warning pops up which is a concern:
Passing '_weak id' to parameter of
incompatible type 'id'
Property declaration in first navigation view is like this:
#property (nonatomic, weak) id <CreateCastStepOneVCDelegate> delegate;
Property declaration is second navigation view is like this:
#property (nonatomic, weak) id <CreateCastStepTwoVCDelegate> delegate;
How have you declared the delegate property on CreateCastStepTwoVC? Also,
are your delegates conforming to a protocol you have defined?
A typical declaration for a delegate property would look something like this:
#property (nonatomic, __unsafe_unretained) id<MyProtocol> delegate;
or if you're not using a protocol (not recommended):
#property (nonatomic, __unsafe_unretained) id delegate;
EDIT:
Having seen your property declarations, you need to change weak to __unsafe_unretained as per this question: Recommended way to declare delegate properties with ARC
You can subclass UINavigationController and add a custom protocol in your subclass. With this approach you will be able to call your delegate from all your view controllers inside your navigation controller. For example, this is the way I used to do that:
#class CustomNavigationController;
#protocol CustomNavControllerDelegate <NSObject>
- (void)editImageController:(CustomNavControllerDelegate *)controller
didFinishPickingMediaWithInfo:(NSDictionary *)info;
- (void)editImageControllerDidCancel:(CustomNavControllerDelegate *)controller;
#end
#interface CustomNavigationController : UINavigationController
#property (nonatomic, weak) id <UINavigationControllerDelegate, CustomNavControllerDelegate> delegate;
#end
In this example I've implemented a similar functionality to a UIImagePickerController. In fact, this is the way the picker is implemented if you look at it's declaration file.

Understanding custom Delegate

So I have an app, and in the app there is a tableView, I have a uinavigationbarbutton that presents a modal viewController. When the user hits a go button in the modal interface, I want it dismiss the modal view and get some of the information in the modal view. I will than put that info in the tableView. To do this, I wrote a custom delegate, but it doesn’t work. I included my code below. Thanks for any help.
TrackerMainViewController.h //the tableView
#import "NewItemViewController.h"
#interface TrackerMainViewController : UITableViewController <UITableViewDelegate, DetailDelegate>
TrackerMainViewController.m
-(void)finishedAddingFoodItemFromDetail:(NSDate *)date whatWasEaten:(NSString *)whatFood whichMeal:(NSString *)meal {
NSLog(#"in delegate method here");
[self.tableView reloadData];
[self dismissModalViewControllerAnimated:YES];
}
NewItemViewController.h // the modal view
#protocol DetailDelegate <NSObject>
-(void)finishedAddingFoodItemFromDetail:(NSDate *)date whatWasEaten:(NSString *)whatFood whichMeal:(NSString *)meal;
#end
#interface NewItemViewController : UIViewController {
id <DetailDelegate> _delegate;
}
#property (nonatomic, retain) id <DetailDelegate> delegate;
#end
NewItemViewController.h
#implementation NewItemViewController
#synthesize delegate = _delegate;
//the go button in the modal view
- (IBAction)Go:(id)sender {
[self.delegate finishedAddingFoodItemFromDetail:[NSDate date] whatWasEaten:#"chicken" whichMeal:#"breakfast"];
}
I put a log in both the go button and in the implementation of the delegate in the tableview, but only the go log is being called.
Thanks
In the code you posted, you dont set the delegate. You need to set it similar to this detailView.delegate = self, otherwise it is nil. You can send messages to a nil-object without any warning and error, nothing will happen.