I have two uiviewcontroller: MainViewController and SecondaryViewControlle. In MainViewController I do:
[self.view addSubView:SecondaryViewControlle.view];
The SecondaryViewController is a button by pressing the function to be performed by a MainViewController. How to do?
You'd start by defining a protocol in your SecondViewControlle.h file, something like:
#protocol SecondViewControlleDelegate
- (void) doSomething
#end
You would also need to add a "delegate" ivar to your SecondViewControlle .h file. It would be the delegate line:
#interface SecondViewControlle : UIViewController
...
...
...
#property (nonatomic, assign) id delegate; // all you need to do is add this line inside your interface declarations
...
...
...
#end
Then, when you create / instantiate your SecondaryViewControlle from your MainViewController, make certain to add the MainViewController as the delegate like so:
SecondaryViewControlle.delegate = self;
[self.view addSubView:SecondaryViewControlle.view];
Now the "delegate" of your SecondaryViewControlle view controller points back to your MainViewController.
And when the button is pressed, you can simply do something like:
- (IBAction) buttonIsPressed: (id) sender
{
[delegate doSomething];
}
Now, I need to give you some advice here.
1 ) DO NOT use the class names as object names. Instead of having an object named "SecondViewControlle", name it something different (and start it with a lower case, which is Objective-C convention), something like "moreDetailVC".
2) I've told you how to do this with a delegate pattern, but this may not be the most appropriate way to do whatever it is that you're trying to do. After all, the MainViewController object (which should be renamed mainVC to differentiate the object from the class) is not on screen or visible so maybe there's a better place to put the functionality?
Option A
It's quicker, and easier, but lacks the maintainability, since there is no contract stating that SecondaryViewController needs to bother calling anything, and self.parentViewController could be any UIViewController.
Option B
The delegate pattern; this is my preference, it's obvious what's happening, what's required, and there's a nice solid contract that states, if you want to initialise me, give me a delegate.
Option C
If SecondaryViewController has to notify multiple objects, it would be quick to use the NSNotificationCenter, but as with Option A, there's no contract, should you need to notify many objects, you would need to remember to listen for notifications on those objects - since this is not the question, I won't go into detail, it's just here for the information
Option A
Within MainViewController.m, do something like so:
SecondaryViewController *viewcontroller = [[SecondaryViewController alloc] initWithNibName:#"SecondaryView" bundle:nil];
[self addChildViewController:viewcontroller];
//set viewcontroller.view frame
[self.view addSubview:viewcontroller.view];
[viewcontroller didMoveToParentViewController:self];
Inside MainViewController.h
-(void) performButtonClickAction;
Inside MainViewController.m:
-(void) performButtonClickAction {
//Do something constructive
}
and then inside the SecondaryViewController.m:
-(IBAction) buttonPressed:(id) sender {
[self.parentViewController performButtonClickAction];
}
Option B
Inside SecondaryViewController.h
#protocol SecondaryViewControllerDelegate <NSObject>
-(void) eventAFromViewController:(UIViewController *) viewController;
-(void) eventBFromViewController:(UIViewController *) viewController;
#end
#interface SecondaryViewController : UIViewController {
id<SecondaryViewControllerDelegate> delegate;
}
#property (assign, nonatomic) id<SecondaryViewControllerDelegate> delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil delegate:(id<SecondaryViewControllerDelegate>) theDelegate;
#end
Inside SecondaryViewController.m
#synthesize delegate = _delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil delegate:(id<SecondaryViewControllerDelegate>) theDelegate
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.delegate = theDelegate;
}
return self;
}
-(IBAction) buttonPressed:(id) sender {
if( self.delegate != nil ) {
[_delegate eventAFromViewController:self];
}
else {
//No delegate
}
}
Related
I posted a question earlier about the same thing, but now I have made a simple project to show what I am doing, so the problem can be found easier.
I have two viewControllers, one is called ViewController and the other SecondViewController.
I tried sending a NSString called testy to a viewController and logging it, but it returned null.
Here is my code trying to send the string from viewController to secondViewController
ViewController.m
#import "ViewController.h"
#import "SecondViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize cellName;
- (void)viewDidLoad
{
[super viewDidLoad];
cellName = #"testy";
SecondViewController *obj = [[SecondViewController alloc] init];
obj.cellName2 = self.cellName;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
}
#property(nonatomic,retain) NSString *cellName;
#end
SecondViewController.m
#import "SecondViewController.h"
#import "ViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
#synthesize cellName2;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidAppear:(BOOL)animated {
NSLog(#"%#",cellName2);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
SecondViewController.h
#import <UIKit/UIKit.h>
#interface SecondViewController : UIViewController {
}
#property(nonatomic,retain) NSString *cellName2;
#end
Edit
I would like to say that my storyboard has two viewController that each have a button. Each button modally brings you to the other view.
Are you sure viewDidLoad is being called? I think it's not called until the view is loaded. I don't think it's called after an alloc init. Also you are setting the string in obj 2 after init. Even if what you are thinking is correct, the 'viewDidLoad' method may be called before the string is being set.
If you want a variable set on init you need to override viewController 2's init method to something like initWithMyVariable then the var will be set on init.
From: Passing Data between View Controllers
Passing data forward to a view controller from another view controller. You would use this method if you wanted to pass an object/value from one view controller to another view controller that you may be pushing on to a navigation stack.
For this example we will have ViewControllerA and ViewControllerB
To pass a BOOL value from ViewControllerA to ViewControllerB we would do the following.
in ViewControllerB.h create a property for the BOOL
#property(nonatomic) BOOL *isSomethingEnabled;
in ViewControllerA you need to tell it about ViewControllerB so use an
import "ViewControllerB.h"
Then where you want to load the view eg. didSelectRowAtIndex or some IBAction you need to set the property in ViewControllerB before you push it onto nav stack.
ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:#"ViewControllerB" bundle:nil];
viewControllerB.isSomethingEnabled = YES;
[self pushViewController:viewControllerB animated:YES];
This will set isSomethingEnabled in ViewControllerB to BOOL value YES.
It might be worth for all who read this article to mention working patterns passing variables between two views:
Options:
Use global variable: SO answer
Use delegation pattern: SO answer
Use notification infrastructure: article
Persist the value in app's userdefault storage, then read when you need : SO answer
For this particular situation it might be better not to create secondviewcontroller in the firstviewcontroller's viewdidload, but to keep the cellName until that point when a user action happens (eg. button press) and then in that method you just set the newly created secondviewcontroller's cellName2 property.
SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:#"second" bundle:nil];
secondViewController.cellName = self.cellName;
I've tested and it is properly logging the value in secondviewcontroller's viewdidload.
Instead of doing: cellName = #"testy"; You should Call:
self.cellName = #"testy";
Also, When you alloc and init in:
SecondViewController *obj = [[SecondViewController alloc] init];,
the viewDidLoad() for secondViewController is called right at that time and you are initializing it's iVar later in the line obj.cellName2 = self.cellName;
That's why you are having NSLOG as null.
Print the NSLOG in viewWillAppear() of secondViewController and you will see the right value this time.
-Create a initialization method for second view controller to pass the variable..
in secondview controller
.h file
add init method
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil cellString(NSString* )cellName;
and .m file
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil cellString(NSString* )cellName{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
cellName2=cellName;
}
return self;
}
and in ViewController.m for initialization
SecondViewController *obj = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil cellString:self.cellName];
This should work...
Best of luck
In viewcontroller.m you have the following in viewDidLoad:
..
..
SecondViewController *obj = [[SecondViewController alloc] init];
obj.cellName2 = self.cellName;
}
The SecondViewController "obj" is never being presented before the end of viewDidLoad, hence NSLog printing null.
If you are wanting to pass a value to SecondViewController via a storyboard, you will need to use the prepareForSegue method. A good example of using it can be found here.
I am a newbie to iOS world, so please ignore the obvious.
I am pushing a viewController(HelpViewController) on top of another viewController(MainViewController). When a particular action happens in the HelpViewController, I would like to update a variable inside the MainViewController. I understand for this I need to use delegate.
Here is my delegate header...
#protocol ViewControllerDelegate <NSObject>
#required
- (void) switchToggled:(BOOL)status;
#end
// Protocol Definition ends here
#interface ViewDelegate : NSObject
{
// Delegate to respond back
id <ViewControllerDelegate> _delegate;
}
#property (nonatomic,strong) id delegate;
-(void)sendMessage:(BOOL)status; // Instance method
#end
and implementation...
#implementation ViewDelegate
#synthesize delegate;
-(id)init {
self = [super init];
return self;
}
-(void)sendMessage:(BOOL)status
{
[delegate switchToggled:status];
}
- (void)dealloc
{
[super dealloc];
}
#end
So Now If I want to implement Protocol ViewControllerDelegate I need to specify in MainViewController, which I do as follows --
MainViewController <ViewControllerDelegate>
and
#pragma mark - ViewControllerDelegate delegate
-(void)switchToggled:(BOOL)status{
NSLog(#"Switch Toggled(%d) Message passed to MainViewController",status);
}
My question is how do I specify Object, which delegate property needs to point to, so that it can come back to MainViewController's "switchToggled".
One way I do is by having property inside HelpViewController as follows -
MainViewController.m
HelpViewController *helpVC = [[HelpViewController alloc] init];
helpVC.mainView = self;
[self.navigationController pushViewController:helpVC animated:YES];
[helpVC release];
HelpViewController.h
#property (nonatomic) MainViewController *mainView;
HelpViewController.m
#synthesize mainView;
ViewDelegate *myDelegate = [[ViewDelegate alloc] init];
// assign delegate
myDelegate.delegate = mainView;
[myDelegate sendMessage];
[myDelegate release];
Is this correct way to implement or there is better way to achieve this or am I totally wrong.
Thanks
You should do:
// HelpViewController.h
#protocol HelpDelegate
- (void)switchToggled:(BOOL)status;
#end
// HelpViewController.m
#interface HelpViewController : UIViewController
#property (nonatomic, assign) id<HelpDelegate> delegate;
- (id)initWithDelegate:(id<HelpDelegate>)delegate
#end
#implementation HelpViewController
- (id)initWithDelegate:(id<HelpDelegate>)delegate
{
if (self = [super init])
{
self.delegate = delegate;
}
}
- (void)sendMessage:(BOOL)status
{
[self.delegate switchToggled:status];
}
// MainViewController.h
#import "HelpViewController.h"
#interface MainViewController.h : UIViewController <HelpDelegate>
// MainViewController.m
- (void)someMethod
{
HelpViewController* viewController;
viewController = [HelpViewController alloc] initWithDelegate:self];
...
}
#pragma mark - Help Delegate
- (void)switchToggled:(BOOL)status
{
...
}
Give the delegate a name that makes clear to which class it belongs.
You don't need the extra class/files for ViewDelegate/ViewControllerDelegate. Just define the delegate in header of class it belongs to: HelpViewController.n in this case.
Similar: Implement the delegate method switchToggled: in the real class MainViewController, and not in the extra/unnecessary class ViewDelegate.
The purpose of delegates is to avoid class dependencies. By including MainViewController in HelpViewController you create such a dependency. This is not necessary as I show, and is wrong design.
You were also creating a circular dependency, because MainViewController already needed HelpViewController in order to show it, and now they need each other the other way around for sending the event.
Alternatively you can make HelpViewController's delegate public, have an init without argument, and expect users to set it with helpViewController.delegate = self; or something. But this would only make sense when the delegate being set is optional (which don't seems the case here, so adding it to the init method is appropriate).
I tell you what I would have done:
1) the protocol definition is ok, but do NOT create the class ViewDelegate, so:
//ViewControllerDelegate.h
#protocol ViewControllerDelegate <NSObject>
#required
- (void) switchToggled:(BOOL)status;
#end
2) Your implementation of the delegate method in MainViewController is ok.
3) Now... the important point:
//interface
#interface HelpViewController : UIViewController //or whatever superclass..
{
id <ViewControllerDelegate> _delegate;
}
#property (nonatomic,strong) id<ViewControllerDelegate> delegate;
#end
//implementation
#implementation HelpViewController
- (void)someMethodWhichCallsTheDelegate
{
//do something
...
// call delegate
//if switchToggled: were optional then add the following
//if ([self.delegate respondToSelector:#selector(switchToggled:)]) {
[self.delegate switchToggled:status];
}
#end
4) Now you have to assign the delegate:
//MainViewController.m
HelpViewController *helpVC = [[HelpViewController alloc] init];
helpVC.delegate = self;
[self.navigationController pushViewController:helpVC animated:YES];
[helpVC release];
And that's it!
BTW: if this delegate is related only to HelpViewControllerthen add the protocol definition where you define the interface of the class, it is not necessary to create a separate header file. If instead the protocol is "global", then it can have some sense to declare it separately.
So I'm fairly new to objective-c and am trying to wrap my head around protocols. I'll use an example to illustrate my question.
Suppose I have a "Calculate" class that performs various methods. I also have "Class1" and "Class2" that perform the same methods in "Calculate".
Now from my understanding I can use protocols to access methods from "Calculate" without the need for inheritance (Therefore saving the need to replicate the same code in Class1 and Class2).
My understanding is also that I have to implement the protocols in Class1 and Class2, therefore I'd have to type out those methods anyways. So whats the point of protocols?
I want to use the methods of "Calculate" without making it a superclass of Class1 and Class2. So I started exploring protocols, I've read the documentation but I still don't understand how this is being achieved. If some one can explain protocols in layman's it would be appreciated.
Inheritance would allow you to not have to duplicate code. Protocols (what other programming languages call interfaces) implement a Can-Do structure of OOP. Meaning when a class implements a protocol, that class is saying that it can do a certain set of methods. It is still up to that class to implement the method as they see fit.
Here is a developer reference from Apple:
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProtocols.html
A protocol is a set of method declarations. It's main purpose is to allow flexible relationships between classes.
Let's say I want a variety of classes to send out logging messages but I don't want them responsible for knowing what happens to the messages after they're sent. I create a Logger protocol that is then implemented by a ConsoleWriter class and a DiskWriter class. The class wanting to send the message doesn't know or care which one it's talking to; it just talks to something it knows as id<Logger>.
I don't know with what types of languages you have experience. But an Object-C protocol is very much like an Interface in .NET. It's purpose is to define a contract (interface, footprint, etc.) so that the actual "Type" of the object is not necessary to be known, but just what it can do.
That being said you can define a protocol "MyProtocol.h" that has a few properties and methods. Then you can implement this protocol on a class. You will not need to add the members of the protocol in the header of the class, but simply need to write the concrete implementation in the implementation.
What this does is allow you to reference object by their defined interface and not their type. So you can use the id type instead of the actual class type.
Hope this helps.
Protocols are almost like a portable header file. They describe methods that can or should be implemented by any class that conforms to the protocol. This is different from inheritance where a subclass automatically implements the methods of its super class and those methods can optionally be overridden on a subclass by subclass basis.
I suspect that you have some OOP background so I won't go too much into subclassing other than to say a subclass is very often a specialized or more specific version of the super class. In other words: every subclass is a kind of its superclass, but every superclass is not necessarily a type of subclass.
Protocols in ObjC are often used in delegate patterns where ClassA needs to know that ClassB can perform some kind of action. Here's an example:
// ClassA.h
#import "ClassB.h"
#interface ClassA <ClassBProtocol>
// Some variables
#end
// ClassA.m
#implementation ClassA
- (id)init {
if ( (self = [super init]) ) {
ClassB *classB = [[ClassB alloc] init]; // Create an instance of ClassB
classB.delegate = self; // Set ourself as the delegate which means we want ClassB to tell us what to do
}
return self;
}
// Introduced by ClassBProtocol
- (void)doSomethingCoolWithString:(NSString *)string {
// Do something here, it's up to ClassA what to do
}
#end
// ClassB.h
#protocol ClassBProtocol <NSObject>
- (void)doSomethingCoolWithString:(NSString *)string;
#end
#interface ClassB
#property (nonatomic, weak) id <ClassBProtocol>delegate;
// Some variables
#end
//ClassB.m
#implementation ClassB
#synthesize delegate;
- (id)init {
if ( (self = [super init]) ) {
if (delegate && [delegate respondsToSelector:#selector(doSomethingCoolWithString:)]) {
[delegate doSomethingCoolWithString:#"A String"];
}
}
return self;
}
#end
Below Example for Simple Protocol & Property:
---> ViewController.h File
#import <UIKit/UIKit.h>
#import "MyVC.h"
#interface ViewController : UIViewController<MyVCProtocol>
{
IBOutlet UILabel *label;
IBOutlet UIButton *btnPush;
MyVC *vc;
}
-(IBAction)Buttonclicked;
#end
---> ViewController.m File
#import "ViewController.h"
#implementation ViewController
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
}
-(IBAction)Buttonclicked
{
vc = [[MyVC alloc]initWithNibName:#"MyVC" bundle:nil];
vc.delegate=self;
[self.navigationController pushViewController:vc animated:YES];
}
-(void)GetText:(NSString *)text
{
label.textAlignment=UITextAlignmentCenter;
label.text=text;
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
---> MyVC.h File
#import <UIKit/UIKit.h>
#protocol MyVCProtocol <NSObject>
-(void)GetText:(NSString *)text;
#end
#interface MyVC : UIViewController
{
IBOutlet UITextField *m_TextField;
IBOutlet UIButton *m_Button;
id <MyVCProtocol> delegate;
}
#property(nonatomic, retain)id <MyVCProtocol> delegate;
-(IBAction)ButtonClicked;
#end
---> MyVC.m File
#import "MyVC.h"
#implementation MyVC
#synthesize delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
}
-(IBAction)ButtonClicked
{
[delegate GetText:m_TextField.text];
[self.navigationController popViewControllerAnimated:YES];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
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];