Passing data between view controllers using protocol and delegate - iphone

I am trying to push a string text to viewcontroller 1 from my viewcontroller 2 using protocols and delegate. I am new to this method of passing data so forgive me if I seem ignorant in any way. The string color always return null. I will post the code I have so far and if it helps, im using navigation controller and using the navigation back button to go from ViewController 2 to ViewController 1.
Viewcontroller 2
.h
#protocol PassString <NSObject>
#required
- (void) setSecondFavoriteColor:(NSString *)string;
#end
#interface ViewController2 : UIViewController{
UIButton *button;
NSString *ee
id <PassString> delegate;
}
#property (retain) id delegate;
ViewController 2
.m
#synthesize delegate;
-(void)button{
ee = #"Blue Color";
[[self delegate] setSecondFavoriteColor:ee];
ViewController 1.h
#interface ViewController1 : UIViewController <PassString>{
NSString*color;
}
#property (strong,nonatomic) NSString *color
ViewController 1.m
- (void)setSecondFavoriteColor:(NSString *)string
{
color = string;
NSLog(#"%#",color);
}

Just a couple things I noticed in your code, your property should contain the specified protocol:
#property (retain) id <PassString> delegate;
And at some point in the class that's implementing the delegate methods, you have to assign the delegate to view controller 1. For example:
[viewController2Instance setPassingDelegate:self];

Related

How to call a method from a UIViewController thats already on the UINavigationController stack

I have a UIViewController on a UINavigationStack and from this UIView I load another view not onto the stack but as a subview. This view that I load is just a preferences view for the app that I overlay onto what ever is showing.
i.e.
myViewController <- on the stack button touch loads as a subview to myViewController
+ prefrencesViewController
My question is, is there a way to call a method thats in myViewController from prefrencesViewController? I am trying to use delegates and protocols but its not working, so I am hoping there is either an easy way to do this I don't know about yet or maybe I could get some help with my delegate/protocol...
This is what my code looks like for delegate and protocol set up
//prefrencesViewController.h
#protocol GetPrefrencesViewControllerDelegate <NSObject>
-(void)reloadViewFromSavedPrefrences;
#end
//delegates and protocols
#property (nonatomic, weak) id <GetPrefrencesViewControllerDelegate> delegate;
//prefrencesViewController.m
//delegates and protocols
#synthesize delegate;
//.. inside button action
[[self delegate] reloadViewFromSavedPrefrences];
//myViewController.h
#import "prefrencesViewController.h"
#interface myViewController : UIViewController <UITabBarDelegate, GetGUIEncodedData, GetPrefrencesViewControllerDelegate> {
// prefrencesViewController set up
prefrencesViewController *pvc;
#property (strong, nonatomic) prefrencesViewController *pvc;
//myViewontroller.h
#synthesize pvc;
- (void)viewDidLoad
{
//..
[pvc setDelegate:self];
}
//Delegate and prefrences.. Saved pressed reload the view here.
-(void)reloadViewFromSavedPrefrences {
NSLog(#"WORKED");
}
any help would be greatly appreciated
I'm not sure that you are following the steps that I will present below but if you don't here is the example.
PresentedViewController.h
//import stuff
#protocol PresentedViewControllerDelegate <NSObject>
-(void)methodThatSouldBeImplementedByOtherController; //you can add params
#end
#interface PresentedViewController : UIViewController {
//instance variables
}
#property (nonatomic, assign(week for ARK)) id<PresentedViewControllerDelegate>delegate
//public methods here
PresentedViewController.m
#implementation PresentedViewController
#synthesize delegate;
//method implementation here
-(IBAction)buttonThatWillCallTheDelegate:(id)sender {
if([self.delegate respondsToSelector:#selector(methodThatSouldBeImplementedByOtherController)]) {
[self.delegate methodThatSouldBeImplementedByOtherController];
}
}
ControllerThatWillPresent.h
#interface ControllerThatWillPresent : UIViewController <PresentedViewControllerDelegate> {
//instance variables
}
//some methods maybe
ControllerThatWillPresen.m
#implementation ControllerThatWillPresen
-(void)methodThatWillShowTheVC {
PresentedViewController *vc = [PresentedViewController alloc] init]; //initWithNibname...
vc.delegate = self;
//presentVc, pushVc, addChild ...
}
-(void)methodThatSouldBeImplementedByOtherController {
//do stuff in delegate method
}

calling functions and passing information between views

Thanks in advance for your help!
In the main ViewController.m of my project I am adding a customized tableView like so:
messageController = [[MyMessagesController alloc] initWithStyle:UITableViewStylePlain];
[self addChildViewController:messageController];
[self.view addSubview:messageController.view];
Then, in the MyMessagesController.m section tableView didSelectRowAtIndexPath: I'd like to write code that would take effect in the ViewController.m where it was created and added as a childViewController.
How can I access the functions of the ViewController.m from MyMessagesController.m?
Can I make it a delegate somehow so I could call [delegate functionName];?
Could I pass information back to the ViewController.m? About which of the rows in table was selected by sending through an NSString or NSArray or anything?
Yes, use a delegate, if you are unsure how best to accomplish this, here is a good reference from Apple about delegate programming
Got it figured out, here's how you turn one viewController into a delegate for another:
In the .h of the parent controller -
#interface ViewController : UIViewController <NameOfDelegate> {
In the .m of the parent controller, once you create the new view -
newViewController.delegate = self;
and also:
- (void)functionToCall:(id)sender {
NSLog(#"Function Called!!!");
}
In the .h of the newViewController you're adding -
#protocol NameOfDelegate;
#interface newViewController : UIViewController/OR/TableViewController {
id <NameOfDelegate> delegate;
}
#property (nonatomic, strong) id <NameOfDelegate> delegate;
#end
#protocol NameOfDelegate
- (void)functionToCall:(id)sender;
#end
in the .m of the newViewController -
#implementation newViewController
#synthesize delegate;
and when you're ready to call the function in your delegate -
[delegate functionToCall:self];

EXD_BAD_ACCESS passing data back to delegate

I'm a relatively new iPhone developer and am making great progress building my 2nd iPhone app. In the app I'm building now I'm doing some code separation with some protocols and delegates so that I car re-use some of my code in a variety of places throughout my code.
Here's what I want to happen:
CITRootViewController creates an instance of a CITReportCreator class, passing itself as a property so that the reportCreator can open additional view controllers and such.
CITReportCreator class is declared as implementing the CITImageCaptureDelegate protocol, which is declared in the CITImageCaptureViewController file.
CITImageCaptureViewController defines the delegate protocol and has a method that passes back data and references to the child view controller so that CITReportCreator can interact with it's data, close the related XIB, etc.
I believe I'm getting the delegate and protocol established correctly, and verified that my 'delegate' object still contains data when it is called, but I'm getting a EXC_BAD_ACCESS method when my view controller tries to pass data back to the delegate in this line of code:
[self.delegate childViewControllerDidFinish:self];
Here's a good portion of the rest of my code. I had this working by using CITRootViewController as my delegate instead of the CITReportCreator class, but now that I'm separating the code, something has broke.
CITReootViewController.m (the view controller that calls the Report Creator)
//create a nrew report
-(IBAction)createReport:(id)sender {
CITReportCreator *report = [CITReportCreator alloc];
[report createNewReport:self];
}
CITReportCreator.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "CITImageCaptureViewController.h"
#interface CITReportCreator : NSObject <CITImageCaptureDelegate>
#property (strong, nonatomic) NSArray *imageList;
#property (nonatomic) NSInteger imageIndex;
-(int) createNewReport:(UIViewController *)parent ;
//Delegate Methods
-(void) childViewControllerDidFinish:(UIViewController*)viewController;
#end
And CITReportCreator.m
#import "CITReportCreator.h"
#implementation CITReportCreator
{
UIViewController *parentController;
}
#synthesize imageList;
#synthesize imageIndex;
-(int) createNewReport:(UIViewController *)parent
{
//store a reference to the parent view controller
parentController = parent;
// init code....
//head to the first image capture view
[self startImageCapture];
return 0;
}
-(int)startImageCapture
{
//pull the image name from the array of images
NSString *imageName = [imageList objectAtIndex:imageIndex];
//prep the image capture controller
CITImageCaptureViewController *capture = [[CITImageCaptureViewController alloc] initWithNibName:#"CITImageCaptureViewController" bundle:nil];
//Assign the capture controller's delegate
capture.imageName = imageName;
capture.delegate = self;
//Display the capture controller
[parentController presentModalViewController:capture animated:YES];
return 0;
}
//a break point set here never gets hit.
-(void) childViewControllerDidFinish:(UIViewController*)viewController;
{
[viewController dismissModalViewControllerAnimated:YES];
}
#end
And finally, the CITImageCaptureViewControllers
CITImageCaptureViewController.h
#import <UIKit/UIKit.h>
#protocol CITImageCaptureDelegate <NSObject>
-(void) childViewControllerDidFinish:(UIViewController*)viewController;
#end
#interface CITImageCaptureViewController : UIViewController
{
id<CITImageCaptureDelegate> delegate;
}
#property (nonatomic,assign) id<CITImageCaptureDelegate> delegate;
#property (nonatomic, assign) NSString *imageName;
//continue button pressed method
-(IBAction)continueButtonPressed:(id)sender;
#end
And the .m file
#import "CITImageCaptureViewController.h"
#interface CITImageCaptureViewController ()
#end
#implementation CITImageCaptureViewController
#synthesize navItem;
#synthesize imageName;
#synthesize delegate = _delegate; //i think this may be part of the problem
//cutting out initWithNibName, viewDidLoad, etc...
- (IBAction)continueButtonPressed:(id)sender
{
[self.delegate childViewControllerDidFinish:self];
}
#end
I find nothing with delegates and protocols all that simple, but I'm guessing I'm missing a small change somewhere. Can you help me head in the right direction?

How to use delegate methods to pass objects between two view controllers?

I'm using the Utility Application project to Xcode 4.2, then I am adding two text fields for each view: main view and the flipside view.
Now I wish to assign the value of the flipside text field to mainview text field.
MainViewController.h
#import "FlipsideViewController.h"
#interface MainViewController : UIViewController <FlipsideViewControllerDelegate> {
UITextField *nameField;
}
#property(nonatomic, retain) IBOutlet UITextField *nameField;
- (IBAction)showInfo:(id)sender;
#end
FlipsideViewController.h
#class FlipsideViewController;
#protocol FlipsideViewControllerDelegate
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller;
#end
#interface FlipsideViewController : UIViewController {
UITextField *changeText;
}
#property (nonatomic, retain) IBOutlet UITextField *changeText;
#property (assign, nonatomic) IBOutlet id <FlipsideViewControllerDelegate> delegate;
- (IBAction)done:(id)sender;
#end
FlipsideViewController.m
#import "FlipsideViewController.h"
#implementation FlipsideViewController
#synthesize delegate = _delegate;
#synthesize changeText;
- (IBAction)done:(id)sender
{
[self.delegate flipsideViewControllerDidFinish:self];
}
When the done action starts, i want the changetext value be assigned to nameField text.
How do I do this?
In MainViewController.m, implement the flipSideViewControllerDelegate method as:
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller
{
self.nameField.text=controller.changeText.text;
}
So when the done: method is called, this delegate method is also called with your flipSideViewController object as the argument, through which changeText can be accessed.
EDIT to answer question in comment:
In your protocol FlipSideViewControllerDelegate, add this method:
- (void)flipsideViewControllerDidSelect:(NSIndexPath*)indexPath
Then it is similar to the other delegate method implementation in MainViewController.m
, which is how the protocol works really. If your MainViewController conforms to the protocol, it can implement methods of that protocol. By default all the methods declared in the protocol are optional, but you have the option to specify if the method is optional or required by using
#optional
//list of methods
#required
//list of methods
Bear in mind that if your a method is declared as required in the protocol, any class conforming to that protocol must implement it. Anyway, in your MainViewController.m:
- (void)flipsideViewControllerDidSelect:(NSIndexPath*)indexPath
{
int anInt=indexPath.row;
self.nameField.text=[NSString stringWithFormat:#"%d",anInt];
}

Calling a function from another UIViewController

I'm a beginner programmmer, this is for xcode - iPhone. although i made alot of my iPhone app but i seem to lack some understanding of how a simple communication might work.
Specially when I've got 2 ViewControllers.
And I wana call one function of a ViewController from another ViewController. Both are under a tabbarController. What I want to achieve is When I'm in ViewA, after tapping on a tableCell, I Should Invoke a method of ViewB and the NavigationBar of ViewB pushes to viewDetail.
The Following is the code i'm using
in ViewControllerA.h (where I'm calling a method)
#class ViewControllerB;
#interface SmartDDxViewController : UIViewController {
IBOutlet UITableView *tableView;
ViewControllerB *xViewController;
}
#property (nonatomic, retain) UITableView *tableView;
#property (nonatomic, retain) ViewControllerB *xViewController;
And this is what I use to invoke it..ViewControllerA.m
ViewControllerB *ddViewController = [[ViewControllerB alloc] init];
self.xViewController = ddViewController;
[xViewController InitialiseDetailWithId:2 title:#"HEYA"];
Heres the InitialiseDetailWithId code: in ViewControllerB.m
-(void)InitialiseDetailWithId:(NSInteger)pkey title:(NSString *)tt{
NSLog(#"InitialiseDetailC=========================================");
AppDelegate *appDelegate = (Smart_DifferentialsAppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate GetConditionDetailsWithId:pkey];
DDisViewController *viewController= [[DDisViewController alloc] initWithNibName:#"DetailView" bundle:nil];
viewController.title = tt;
[self.NavBar pushViewController:viewController animated:YES];
//[tt release];
[viewController release];
viewController = nil;
[self say:#"HEYA"]; //this is ALERTVIEW box that displays HEYA
}
I'm getting all information fine, and the alertview does get displayed. But when I chose that View in TabBar, its not pushed.
Do not use direct access between view controllers, instead use the delegate pattern. Define your controller like this:
#protocol ViewControllerAInitDelegate;
#interface ViewControllerA : UIViewController {
IBOutlet UITableView *tableView;
id<ViewControllerAInitDelegate> initDelegate;
}
#property (nonatomic, retain) UITableView *tableView;
#property (nonatomic, assign) ViewControllerAInitDelegate *initDelegate;
#end
#protocol ViewControllerInitDelegate
-(void)initializeDetailWithId:(NSInteger)pkey title:(NSString)tt;
#end
So in
Now let your application delegate conform to the ViewControllerInitDelegate protocol. It should look something like this:
#interface AppDelegate : NSObject <UIApplicationDelegate, ViewControllerInitDelegate> {
IBOutlet UITabBarControler* tabBarController;
IBOutlet ViewControllerA* controllerA;
IBOutlet ViewControllerB* controllerB;
}
#end;
The AppDelegate should know about both ViewControllerA, and ViewControllerB, but neither of the view controller should know about each other. This way it will be much easier to debug and extend your app.
//current view controller index
int currentVCIndex = [self.navigationController.viewControllers indexOfObject:self.navigationController.topViewController];
//previous view controller (index -1)
AccountViewController *account = (AccountViewController *)[self.navigationController.viewControllers objectAtIndex:currentVCIndex - 1];
(access to anything you want)
account.property = object;
[account doSmthng];
In each of your view controllers, you might want to add a instance variable/property to keep track of the other view controller.
you might have for example:
#interface ThisViewController : UIViewController {
SomeViewController *sViewController;
// other instance variables
}
#property (nonatomic, retain) SomeViewController *sViewController;
This not only makes it easier to call methods from the other view controller and access its public properties, but it also allows you an easier way of flipping between the two (with or without animation).