In this code I'm attempting to pass an array from one tab view to another using protocols. The method itself is a simple get method with one line returning an a mutableArray. Within it's own class it works, within this class it is not even called.
- (void)viewDidLoad
{
[super viewDidLoad];
myLocationEntityArray = [[NSMutableArray alloc] initWithArray:[[self delegate] getMyLocationEntityArray]];
}
The header file for the class receiving the data:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#protocol CoreDataDelegate;
#interface ListTableViewController : UITableViewController
{
NSManagedObjectContext *managedObjectContext;
NSMutableArray *myLocationEntityArray;
id <CoreDataDelegate> delegate;
}
- (NSMutableArray *)fetchCoreData;
#property(nonatomic, retain) NSManagedObjectContext *managedObjectContext;
#property(nonatomic, assign) id <CoreDataDelegate> delegate;
#property(nonatomic, retain) NSMutableArray *myLocationEntityArray;
#end
#protocol CoreDataDelegate
//- (NSMutableArray *) fetchCoreData;
- (NSMutableArray *) getMyLocationEntityArray;
#end
The top of the header file sending the data:
#interface MapViewController : UIViewController <CLLocationManagerDelegate, CoreDataDelegate>
First you should change your procotol like this :
#protocol CoreDataDelegate
//- (NSMutableArray *) fetchCoreData;
- (void) getMyLocationEntityArray:(NSMutableArray *)entityArray;
#end
You set your MapViewController to responds to your protocol CoreDateDelegate. So, I suppose you alloc your ListTableViewController inside the MapViewController. If that is the case, you need to do this :
// MapViewController.m
...
ListTableViewController *listVC = [[ListTableViewController alloc] init];
listVC.delegate = self;
// display your listVC
...
// Somewhere in your code of MapViewController.m
- (void) getMyLocationEntityArray:(NSMutableArray *)entityArray {
// do something with entityArray
}
EDIT
Following your comments, here is a simpler way to do what you want. NSNotification. It does not require protocol, and is easier to implement.
// In ListTableViewController.m
// In Init or viewDidLoad function
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(getEntity:)
name:#"GetEntity"
object:nil];
- (void)getEntity:(NSNotification *)notif {
NSArray *entityArray = (NSArray *)[notif object];
// do something with entityArray
}
// In dealloc or viewDidUnLoad function
[[NSNotificationCenter defaultCenter] removeObserver:self
name:#"GetEntity"
object:nil];
// In MapViewController.m
// theEntityArray to be defined
[[NSNotificationCenter defaultCenter] postNotificationName:#"GetEntity"
object:theEntityArray
userInfo:nil];
In few words, when you will post the GetEntity notification in MapViewController, it will call undirectly the -(void)getEntity: function of ListTableViewController
Related
I started testing ECSlidingViewController and after I tried to access FirstTopViewController I have a big trouble - because in FirstToViewController I already have ZBarReaderDelegate implemented and all examples of delegate are not triggering any method from my delegate.
Basically I have this stuff:
FirstTopViewController.h
#import ...MyStuff...
#import "UnderRightViewController.h"
#interface FirstTopViewController : UIViewController <RightViewDelegate, ZBarReaderDelegate>
#property (weak, nonatomic) IBOutlet UITextView *labelTotal;
#end
FirstTopViewController.m
#import "FirstTopViewController.h"
#implementation FirstTopViewController
- (void)setTotalViewController:(UnderRightViewController*)controller didTotalChange:(NSString*)total
{
//labelTotal.text = total;
NSLog(#"I'm here!!! and received %#", total);
}
From other side I have
UnderRightViewController.h
#import <UIKit/UIKit.h>
#import "ECSlidingViewController.h"
#class UnderRightViewController;
#protocol RightViewDelegate <NSObject>
- (void)setTotalViewController:(UnderRightViewController*)controller didTotalChange:(NSString*)total;
#end
#interface UnderRightViewController : UITableViewController
#property (nonatomic, weak) id <RightViewDelegate> delegate;
#end
UnderRightViewController.m
#import "UnderRightViewController.h"
#interface UnderRightViewController ()
#end
#implementation UnderRightViewController
#synthesize delegate;
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[delegate setTotalViewController:self didTotalChange:#"foo"];
}
#end
I'm trying this entire day solve this puzzle but I never get setTotalViewController fired.
Thanks in advance.
Friend you did a small mistake, when you navigate from FirstTopViewController to UnderRightViewController at that time you need to do this in FirstTopViewController.m:-
UnderRightViewController *obj = [[UnderRightViewController
alloc] initWithNibName:#"UnderRightViewController" bundle:nil];
obj.delegate = self; // u forget to assign protocol handler
[self.navigationController pushViewController:obj animated:YES];
[obj release];
You don't have any code that is setting the delegate for the UnderRightViewController. I don't know what object owns both of these controllers, but before either UnderRightViewController and FirstTopViewController are displayed it should run code something like this:
FirstTopViewController *ftvc = //... where ever you get a reference to this from
UnderRightViewController *urvc = ...;
urvc.delegate = ftvc;
In your above code you are using custom delegates and also you have used it for sending message to onecontroller class to another controller class. So below is the same sample code of custom delegates, it is working fine in similar way you have to implement and also the problem in your code is you are not setting the delegate, so please follow below how to set the same and call the method. here i have used your same method only return type i have defined as NSString in-spite of void for explaining purpose, but you can use void according to your requirement hope it will be helpful to you:-
First Controller Class AWindowController.h
#interface AWindowController : NSWindowController<sampleDelegate>
{
NSString *textA;
}
#property(readwrite,retain)NSString *textA;
-(IBAction)doSet:(id)sender;
#end
#import "AWindowController.h"
#import "BWindowController.h"
#interface AWindowController ()
#end
#implementation AWindowController
#synthesize textA;
- (id)initWithWindow:(NSWindow *)window
{
self = [super initWithWindow:window];
if (self) {
// Initialization code here.
}
return self;
}
- (NSString *)setTotalViewController:(BWindowController*)controller didTotalChange:(NSString*)total
{
NSLog(#"recieved");
return #"recieved";
}
- (void)windowDidLoad
{
[super windowDidLoad];
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
}
-(NSString*)windowNibName
{
return #"AWindowController";
}
-(IBAction)doSet:(id)sender
{
[self setTextA:#"Awindow Button Pressed"];
BWindowController *b=[[BWindowController alloc]init];
b.delegate=self;
[b showWindow:self];
}
#end
Second Controller Class BWindowController.h
#import <Cocoa/Cocoa.h>
#import "sampleDelegate.h"
#class BWindowController;
#protocol sampleDelegate <NSObject>
#required
//-(NSString *)getDataValue;
- (NSString *)setTotalViewController:(BWindowController*)controller didTotalChange:(NSString*)total;
#end
#interface BWindowController : NSWindowController<sampleDelegate>
{
NSString *bTextValue;
id<sampleDelegate>delegate;
}
#property(readwrite,retain)NSString *bTextValue;
#property(readwrite,assign)id<sampleDelegate>delegate;
#end
#import "BWindowController.h"
#interface BWindowController ()
#end
#implementation BWindowController
#synthesize bTextValue,delegate;
- (id)initWithWindow:(NSWindow *)window
{
self = [super initWithWindow:window];
if (self) {
// Initialization code here.
}
return self;
}
- (NSString *)setTotalViewController:(BWindowController*)controller didTotalChange:(NSString*)total;
{
return nil;
}
- (void)windowDidLoad
{
NSString *str= [[self delegate]setTotalViewController:self didTotalChange:#"recieved"];
self.bTextValue=str;
[super windowDidLoad];
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
}
-(NSString*)windowNibName
{
return #"BWindowController";
}
#end
Attached screen shot in Output:-
Below is window is the AwindowController.h class
Below in the same above window pressing the button and when Awindow button pressed data will send
and notification will be recieved in Bwindow using above define custom delegates as attached in the screen shot.
I'm working on an iPad App and i'm having issue with delegate... the protocol method does not get invoked. i'm not sure what i'm missing, here is my code.
#protocol pickerLabelProtocol <NSObject>
- (void)selectedPickerData:(UILabel *)sender;
#end
#interface showPickerVC : UIViewController
#property (nonatomic, strong) id <pickerLabelProtocol> delegate;
#end
#implementation showPickerVC
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
//i used breakpoint, the 'delegate' is always nil for some reason?
[self.delegate selectedPickerData:self.mainLabel];
}
----------------------
#interface someViewController : UIViewController <pickerLabelProtocol>
#property (nonatomic, strong) showPickerVC *showPicker;
#end
#implementation someViewController
- (void)selectedPickerData:(UILabel *)sender
{
//protocol method
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.showPicker = [[showPickerVC alloc]init];
self.showPicker.delegate = self;
}
I can not got any mistake From your code but i suggest you that Be clear about when you create object of showPickerVC add it's delegate self
Such Like ,
showPickerVC *obj = [[showPickerVC alloc] init];
obj.delegate = self; /// YOur protocol delegate
.
.
[self presentModalViewController:obj animated:YES];
And Also add code as following
#implementation showPickerVC
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if([self.delegate respondsToSelector:#selector(selectedPickerData:)])
{
[self.delegate selectedPickerData:self.mainLabel];
}
}
For More information about How to create/use of Protocol.
I have 4 classes i.e views in my application. Class A, having variable a and b.
After clicking on button which is on view A of class A it leads to class B, which is table view controller. Then class B leads to class C. then class C leads to class D.
Now i want to access values of a and b of class A into class D. I tried it with NSNotification but not succeeded.
Please suggest.
I tried with NSNotification:
i tried with NSNotification like Class A---
-(IBAction) selectButton:(id) sender{
NSString * a = [NSString stringWithFormat:#"Manjinder singh"];
NSDictionary * dict = [NSDictionary dictionaryWithObject:a forKey:#"1"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"sendMessage" object:self userInfo:dict];
}
Then Class D----
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(sendMessage:) name:#"sendMessage" object:nil];
}
return self;
}
-(void)sendMessage:(NSNotification *)notification{
A *dil=[[A alloc] init];
nslog(#"dil.a");
NSLog(#"USERINFO:MyUserInfo (its a dictionary):%#",[[notification userInfo] valueForKey:#"1"]);
}
This is the rendom try but basically i want to show variable a and b of class A into class D.
Update:------------
MyCoolViewController.h// a class where data send from
#protocol MyCoolViewDelegate;
#interface MyCoolViewController : UIViewController {
id <MyCoolViewDelegate> delegate;//
}
#property (nonatomic, assign) id delegate;//
#end
#protocol MyCoolViewDelegate <NSObject>//
-(void)sendAStringToAnotherView:(NSString*)string;
#end
MyCoolViewController.m
-(void)viewDidLoad{
[delegate sendAStringToAnotherView:#"this is a string"];
}
firstViewController.m //a class where data sent
-(void)viewDidLoad{
MyCoolViewController *myViewControllerPointer=[[MyCoolViewController alloc] init];
myViewControllerPointer.delegate = self;//
}
-(void)sendAStringToAnotherView:(NSString*)string
{
//displays the string as console output
NSLog(#"plzzzzzz show data",string);
}
value of string is not passed to this class because it is not showing in NSLog output.
UPDATED 2---
MyCoolViewController.m
#import “MyCoolViewController.h”
#import "firstViewController.h"
#implementation MyCoolViewController
#synthesize label1,sttr;
#synthesize delegate;//
-(IBAction) selectButton:(id) sender{
if (curri==nil) {
curri=[[CurrancyViewController alloc] initWithNibName:nil bundle:nil];
[self.navigationController pushViewController:curri animated:YES];
}
curri=nil;
//CHECK ThIS [curri release];
}
- (void)viewDidLoad
{
[delegate sendAStringToAnotherView:#"this is a string"];
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"background1.png"]];
[super viewDidLoad];
}
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
Can you give more context about what specifically you are trying to achieve? It sounds like you want to pass data between several UIViewControllers. Here is how to set up a delegate for one of your view controllers:
#import <UIKit/UIKit.h>
#protocol MyCoolViewControllerDelegate;
#interface MyCoolViewController : UIViewController {
id <MyCoolViewControllerDelegate> delegate;
}
#property (nonatomic, assign) id delegate;
#end
#protocol MyCoolViewControllerDelegate <NSObject>
-(void)sendAStringToAnotherView:(NSString*)string;
#end
Then you will should synthesize the delegate
#synthesize delegate;
and then when you want to pass data to, lets say a parent view, call this function:
[delegate sendAStringToAnotherView:#"this is a string"];
In the other view controller, wherever you instantiated the instance of this UIViewController, you need to set that self as the delegate;
myViewControllerPointer.delegate = self;
and then implement the delegate function in the parent view controller.
-(void)sendAStringToAnotherView:(NSString*)string
{
//displays the string as console output
NSLog(string);
}
The fact that you need communicate between views like this could possibly mean that there is a more efficient means of structuring your app. Can't say for sure without more info.
Try and use this template to add a delegate to your own app.
You could use delegation here
D would become the delegate of A, and when you click the button, A sends a message to D with the variables as arguments and D responds by performing a method.
I've created a protocol named RecDelegate that's consisted of a method "- (void) doSmtng".
The protocol is defined in rec.h just before the rec interface declaration.
When I create a new application and adopt the RecDelegate to the new appDelegate, I can implement my own doSmtng, as needed to be.
What I don't understand is how can I invoke the doSmtng method from the rec.m (implementation of the class in which the protocol is defined...) - Meaning, how can I "Fire" the doSmtng in such a way that the new appDelegate's implementation will be triggered.
Hope what I said is relatively clear ... ;)
Thanks,
Guy.
There are two controllers below showing how to trigger an event from one to the other.
Wherever there is a comment "//HERE", it indicates there is delegation-related code.
SENDER OF DELEGATE
SecondViewController.h
#import <UIKit/UIKit.h>
#protocol SecondDelegate <NSObject> // HERE
#optional
-(void)MessageReceived:(NSString *)msg;
#end
#interface SecondViewController : UIViewController {
id<SecondDelegate> secondDelegate; // HERE
}
#property (assign) id<SecondDelegate> secondDelegate; // HERE
-(IBAction)trigger:(id)sender;
#end
SecondViewController.m
#import "SecondViewController.h"
#implementation SecondViewController
#synthesize secondDelegate; // HERE
-(IBAction)trigger:(id)sender {
if (self.secondDelegate != NULL && [self.secondDelegate respondsToSelector:#selector(MessageReceived:)]) { // HERE
[secondDelegate MessageReceived:#"my message"];
}
}
RECEIVER OF DELEGATE
FirstViewController.h
#import <UIKit/UIKit.h>
#import "SecondViewController.h" // HERE
#interface FirstViewController : UINavigationController <SecondDelegate> // HERE
-(void)MessageReceived:(NSString*)msg; // HERE
#end
FirstViewController.m
#import "FirstViewController.h"
#import "SecondViewController.h"
#implementation FirstViewController
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
// Custom initialization
[self.view setBackgroundColor:[UIColor greenColor]];
SecondViewController *second = [[SecondViewController alloc] init];
[self pushViewController:second animated:YES];
second.secondDelegate = self; // HERE
[second release];
}
return self;
}
-(void)MessageReceived:(NSString *)msg { // HERE
int y = 0; // HERE IT IS !
}
You need to tell your Rec object that it should treat your AppDelegate as its delegate:
[rec setDelegate:appDelegate];
This could be done via Interface Builder or just after the Rec object is created.
Then, when the Rec object sends the delegate message to its delegate, the receiver will be your AppDelegate instance:
[[self delegate] doSmtng];
If the message the Rec object is sending to its delegate were an optional protocol message, it would instead be sent like this:
if ([[self delegate] respondsToSelector:#selector(optionalProtocolMethod)]) {
[[self delegate] optionalProtocolMethod];
}
The delegate will usually be declared something like:
#property(assign, nonatomic) id<RecDelegate> delegate;
Because it is not retained, in -dealloc, the Rec object only needs to nil it out, not release it:
delegate = nil;
Another way to do something like that is using NSNotificationCenter
in your RecDelegate init method add:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(doSmtng) name:#"someNotification" object:nil];
and in any another place / any class call
[[NSNotificationCenter defaultCenter] postNotificationName:#"someNotification" object:nil];
I know this question as been asked over and over but it's still quite obscure to me, so I guess making an example with my code instead will probably be easier .
I know that you can use :
A global variable, ( not good practice ).
Use a delegate
Use a singleton
Say I've got this piece of code here in my first view controller header :
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController {
IBOutlet UITextField *Te;
NSInteger evTe;
}
#property (nonatomic, retain) UITextField *Te;
#property (nonatomic) NSInteger evTe;
- (IBAction) makeKeyboardGoAway;
#end
and then this in my implementation file
#import "FirstViewController.h"
#implementation FirstViewController
#synthesize Te;
- (IBAction) makeKeyboardGoAway;
{
[Te resignFirstResponder];
evTe = [Te.text intValue];
}
How would I call evTe in my SecondViewController ? ( maybe using a delegate ?) .
This is what I've got in the second view Controller, header :
#interface SecondViewController : UIViewController {
NSInteger evTe;
}
#property (nonatomic) NSInteger evTe;
and implementation :
- (IBAction) makeKeyboardGoAway;
{
FirstViewController *first = [[FirstViewController alloc] init];
first.evTe = self.evTe;
NSLog(#"second value is %i",evTe);
}
Thanks a lot !
Edit for Tob
FirstViewController.m
- (IBAction) makeKeyboardGoAway;
{
evTe = [Te.text intValue];
NSLog(#"The value of integer num is %i", evTe);
NSDictionary *changedValues = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:evTe] forKey:#"evTe"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"evTeChanged" object:self userInfo:changedValues];
}
SecondViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(methodToCall:) name:#"evTeChanged" object:nil];
}
- (void)methodToCall:(NSNotification *)aNotification{
NSDictionary *changedValues = [[aNotification userInfo] objectForKey:#"evTe"];
NSString *dictionaryString = [changedValues description];
NSLog(#"Notification returning %d",dictionaryString);
}
Unfortunately I'm not getting any log from the SecondView ..
By creating a #property called evTe or whatever in both view controllers.
If the FirstViewController is responsible for creating the SecondViewController you could store the value of evTe in a property in FirstViewController and then after you have created the SecondViewController you set the evTe property there as well.
- (IBAction) makeKeyboardGoAway;
{
[Te resignFirstResponder];
self.evTe = [Te.text integerValue];
}
// other method where SecondViewController is created
SecondViewController* second = [[SecondViewController alloc] init];
second.evTe = self.evTe;
// do what ever
--Edit--
#interface FirstViewController : UIViewController {
IBOutlet UITextField *Te;
NSInteger evTe;
}
#property (nonatomic, retain) UITextField *Te;
#property (nonatomic) NSInteger evTe;
Have a look at NSNotification. You should send a notification that the particular value has changed and register for that notification in the second view controller.
- (IBAction) makeKeyboardGoAway;
{
[Te resignFirstResponder];
evTe = [Te.text intValue];
NSDictionary *changedValues = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:evTe] forKey:#"evTe"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"evTeChanged" object:self userInfo:changedValues];
}
And in the viewDidLoad method of the other controller do:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(methodToCall:) name:#"evTeChanged" object:nil];
Now every time the first controller calls makeKeyboardGoAway the method - (void)methodToCall:(NSNotification *)aNotification will be called.
Implement this method and ask the aNotification for its userInfo which is the NSDictionary you created in the first controller before posting the notification. Get the evTe value out of it and do whatever you want to do with that value.