Obj-C Sending Messages Between Classes - iphone

I'm a newbie in iPhone Programming. I'm trying to send a message from one view controller to another. The idea is that viewControllerA takes information from the user and sends it to viewControllerB. viewControllerB is then supposed to display the information in a label.
viewControllerA.h
#import <UIKit/UIKit.h>
#interface viewControllerA : UIViewController
{
int num;
}
-(IBAction)do;
#end
viewControllerA.m
#import "viewControllerA.h"
#import "viewControllerB.h"
#implementation viewControllerA
- (IBAction)do {
//initializing int for example
num = 2;
viewControllerB *viewB = [[viewControllerB alloc] init];
[viewB display:num];
[viewB release];
//viewA is presented as a ModalViewController, so it dismisses itself to return to the
//original view, i know it is not efficient
[self dismissModalViewControllerAnimated:YES];
}
- (void)dealloc {
[super dealloc];
}
#end
viewControllerB.h
#import <UIKit/UIKit.h>
#interface viewControllerB : UIViewController
{
IBOutlet UILabel *label;
}
- (IBAction)openA;
- (void)display:(NSInteger)myNum;
#end
viewControllerB.m
#import "viewControllerB.h"
#import "viewControllerA.h"
#implementation viewControllerB
- (IBAction)openA {
//presents viewControllerA when a button is pressed
viewControllerA *viewA = [[viewControllerA alloc] init];
[self presentModalViewController:viewA animated:YES];
}
- (void)display:(NSInteger)myNum {
NSLog(#"YES");
[label setText:[NSString stringWithFormat:#"%d", myNum]];
}
#end
YES is logged successfully, but the label's text does not change. I have made sure that
all of my connections in Interface Builder are correct, in fact there are other (IBAction)
methods in my program that change the text of this very label, and all of those other methods work perfectly...
Any ideas, guys? You don't need to give me a full solution, any bits of information will help. Thanks.

With
viewControllerB *viewB = [[viewControllerB alloc] init];
you are instantiating a new viewControllerB. This is not the viewControllerB that (I presume) you have in your nib file. You should make an outlet for that and wire it up.
Otherwise, possibly instantiate it with [... initWithNibName:] from a nib, instead of just [... init], and then (either way) push the instantiated view controller using [self.navigationController pushViewController:viewB animated:YES], or by presenting it modally as you seem to have mastered already.
As a sidenote, maybe name the viewcontroller variable viewConB, since there is a clear and important distinction between views and view controllers. Furthermore, class names tend to start with upper case, and variables with lower case, to keep things clear.

Related

how to pass value when popToRoot

will like to know how do i pass value back to the root view controller when i popToRoot.
introVideoViewController *intro = [introVideoViewController alloc];
intro.fromReset =1;
[self.navigationController popToRootViewControllerAnimated:NO];
With the VC that you want to pop back from, you need to give it a delegate property -
#class MyViewController;
#protocol MyViewControllerDelegate <NSObject>
-(void)myViewControllerDidDismiss:(MyViewController *)controller withSomeObject:(id)someObject;
#end
#interface MyViewController : UIViewController
#property (nonatomic, assign) id<MyViewControllerDelegate> myViewControllerDelegate;
#end
...and in the root VC you make it conform to that protocol, and implement the dismiss method -
-(void)myViewControllerDidDismiss:(MyViewController *)controller withSomeObject:(id)someObject {
// now I've got the object from the VC I just popped
}
Forgot to mention that you need to call myViewControllerDidDismiss:withSomeObject: when you pop the VC.
Edit - Also forgot to mention that you need to set the VC's delegate as your root VC when you create it, or else it'll be trying to call nil when you pop back -
[myViewController setMyViewControllerDelegate:self];
Just use the below code
NSArray *arr = [self.navigationController viewControllers];
CLASS_OF_ROOT_VIEW_CONTROLLER *rvc = (CLASS_OF_ROOT_VIEW_CONTROLLER *)[arr objectAtIndex:0];
rvc.variable = value;

XCode: Call action in main view from modal view

I am trying to call an action (changeMainNumber) in a main view controller from a modal view controller. The action should change the UILabel mainNumber to 2. In ViewController.h, I have:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
IBOutlet UILabel *mainNumber;
}
#property (nonatomic, retain) UILabel *mainNumber;
-(IBAction)changeMainNumber;
ViewController.m:
#import "ViewController.h"
#implementation ViewController
#synthesize mainNumber;
- (IBAction)changeMainNumber:(id)sender {
mainNumber.text = #"2";
}
The next view controller is the modal view controller.
ModalViewController.h:
#import <UIKit/UIKit.h>
#class ViewController;
#interface ModalViewController : UIViewController {
}
-(IBAction)callChangeMainNumber:(id)sender;
and ModalViewController.m:
#import "ModalViewController.h"
#implementation ModalViewController
- (IBAction)callChangeMainNumber {
ViewController *viewController = [[ViewController alloc] init];
[viewController changeMainNumber];
}
With this setup the app keeps crashing when callChangeMainNumber is called and I can't figure out what is wrong. Any help you can provide is appreciated!
The code you posted from your ModalViewController is not referencing your ViewController. You are creating a new one in your code. The best solution to your problem would be to make your ViewController a delegate to the ModalViewController.
So in your ModalViewController.h file you should have this code above your #implementation.
#protocol ModalViewControllerDelegate
- (void)shouldChangeMainNumber;
#end
Then in your #implementation of the header have:
#property (nonatomic,assign)IBOutlet id <ModalViewControllerDelegate> delegate;
Now in the .m file where you have your IBAction method, tell the delegate that you want it to change the main number.
- (IBAction)callChangeMainNumber {
[self.delegate shouldChangeMainNumber];
}
Then in your ViewController.m file you need to set yourself as the delegate of the ModalViewController, usually in viewDidLoad is a good place to put it. So create a property in your header for the ModalViewController first and synthesize it, then add this to viewDidLoad.
self.modalViewController.delegate = self;
and finally you need to implement the delegate method in your .m file somewhere
- (void)shouldChangeMainNumber {
mainNumber.text = #"2";
}

Present view from delegate modally in iOS 5

I cannot seem to find this anywhere online. I have an add button in one of my views and I have hooked it up to an IBAction method called add. In my storyboard, I have created a view that has a form all set up on it. I have assigned a class to that view in the storyboard as well. That class is called AddItemViewController.
I am trying to present this view modally and then set the delegate to the view that called the AddItemViewController. However, all I get is an empty UITableViewController that shows up. Here is my code that I'm trying to use:
- (IBAction)add {
AddItemViewController *addItem = [[AddItemViewController alloc] init];
addItem.delegate = self;
[self presentModalViewController:addItem animated:YES];
}
Is there anything I'm missing? Why does it just show an empty table and not the view controller that I set up in the storyboard?
Here is the code from the AddItemViewController:
#interface AddItemViewController : UITableViewController <UITextFieldDelegate> {
}
#property (strong, nonatomic) IBOutlet UITextField *note;
- (void)save:(id)sender;
- (void)cancel:(id)sender;
#end
#implementation AddItemViewController
- (void)viewDidLoad {
}
- (IBAction)cancel:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)save:(id)sender {
DbHandler *db = [[DbHandler alloc] init];
[db executeUpdate:self.note];
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
Well, AddItemViewController inherits from UITableViewController, not UIViewController, so it makes sense that a UITableViewController is showing up.
You should initiate the AddItemViewController like this:
AddItemViewController *addItem = [[AddItemViewController alloc] initWithNibName:#"AddItemViewController"];

Passing Parameter From a View Back To another View's UITableView's Cell

i have got two view.
First: FirstViewController
Second: SecondViewController
FirstViewController is my UINavigationController's root controller and inside FirstViewController I ve got UITableView. When a cell is clicked in UITableView, the view is navigated to SecondViewController. Inside SecondViewController i have UILabel. I want to assign this UILabel's value to the cell which is clicked at FirstViewController when Back button is clicked in Navigation Bar. What am i supposed to do to implement this?
I can pass value to SecondViewController from FirstViewController by creating:
SecondViewController *sv;
sv.somestring = someanotherstring;
but can not implement this at SecondViewController to pass the value to a NSString in FirstViewController.
Can u help me please?
Thank you.
ae
The typical way to handle this in the iPhone SDK is to define a delegate protocol. For instance:
#protocol SecondViewControllerDelegate
- (void) viewControllerWillDisappearWithLabelText: (NSString*)text;
#end
Then you would add a delegate property to your SecondViewController, like:
//in the .h file
#interface SecondViewController : UIViewController {
//declare instance variables
}
#property(nonatomic, assign) id<SecondViewControllerDelegate> delegate;
#end
//in the .m file
#implementation SecondViewController
#synthesize delegate;
//[code...]
#end
Then you would update FirstViewController to implement the delegate protocol:
//in the .h file
#interface FirstViewController : UIViewController<SecondViewControllerDelegate> {
//[instance variables]
}
//[methods and properties]
#end
//in the .m file
#implementation FirstViewController
//[code...]
- (void) viewControllerWillDisappearWithLabelText: (NSString*)text {
//do whatever you need to do with the text
}
//[code...]
#end
...and to set the delegate field when FirstViewController creates the SecondViewController:
SecondViewController* sv = [[SecondViewController alloc] init];
sv.somestring = someanotherstring;
sv.delegate = self;
Finally, in SecondViewController you implement viewWillDisappear to be roughly like:
- (void) viewWillDisappear: (bool)animated {
[super viewWillDisappear:animated];
if (self.delegate) {
[self.delegate viewControllerWillDisappearWithLabelText: myLabel.text];
}
}
Ya , there is much a easy way to handle this.....
You can take a Global Variable
In your Delegate.h file declare your variable:
#interface Smoke_ApplicationAppDelegate : NSObject {
UIWindow *window;
UINavigationController *navigationController;
NSString *messageString; //This would be your String Variable
}
#property(nonatomic,retain)NSString *messageString;
Secondly in Delegate.m file
#implementation Smoke_ApplicationAppDelegate
#synthesize window;
#synthesize navigationController;
#synthesize messageString; // Synthesize it over here..
This is Done .Now you can use this String Variable in All/any class you want..
To use this Global Variable.
Just import you Delegate file make the obj of it....
import "DelegateFile.h"
#implementation About
DelegateFile *appDel;
Now in Your class.m
-(void)viewDidLoad { [super viewDidLoad];
appDel=[[UIApplication sharedApplication]delegate];
}
Now you can access it anywhere in your class by this Object:
appDel.messageString
Just follow my Steps Carefully , I am sure this is definitely going to help you.....
Have a easy life,
Declare a string (stringVal)in the appdeleage and set its propert as nonatomic and retain, synthesize it also.In the second view controller you can set the label value to the appdelegate string([appdelegate setStringVal:label.text];) .You can get this value in the first view controller and use it in table(NSString *localString=appdelegate.stringVal];).
All the best.

Problem with Delegate and NavigationController

I'm using a NavigationController to "push" viewControllers from the rootView of an app.
I want to use delegates to comunicate the currently loaded view and the rootViewController. I was able to do this using NSNotificationCenter, but want give a try to delegates for this particular situation, since the communication is always going to be one-to-one.
In the view that is pushed, I declared the following delegate protocole in the header file:
#import <UIKit/UIKit.h>
#protocol AnotherViewControllerDelegate;
#interface AnotherViewController : UIViewController {
id <AnotherViewControllerDelegate> delegate;
}
- (IBAction) doAction;
#property (nonatomic, assign) id delegate;
#end
#protocol AnotherViewControllerDelegate <NSObject>
- (void) doDelegatedAction:(AnotherViewController *)controller;
#end
The doAction IBAction is connected to a UIButton in the view. In my implementation file, I added:
#import "AnotherViewController.h"
#implementation AnotherViewController
#synthesize delegate;
- (IBAction) doAction {
NSLog(#"doAction");
[self.delegate doDelegatedAction:self];
}
In my RootViewController.h I added AnotherViewControllerDelegate to the interface declaration:
#interface RootViewController : UIViewController <AnotherViewControllerDelegate> {...
and this to my implementation file
- (void) doDelegatedAction:(AnotherViewController *)controller {
NSLog(#"rootviewcontroller->doDelegatedAction");
}
Unfortunately it's not working. doDelegatedAction in the rootViewController is not been called. I suspect it's because of the way I push the AnotherViewController:
AnotherViewController *detailViewController = [[AnotherViewController alloc] initWithNibName:#"AnotherViewController" bundle:nil];
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
Should I tell, in any way, to AnotherViewController that its delegate is going to be RootViewController just in the moment it's been pushed? or am I missing something else?
You need to set the delegate of AnotherViewController to the rootViewController in order for everything to be connected up properly.
If you are initializing AnotherViewController in your rootViewController it would be:
AnotherViewController *detailViewController = [[AnotherViewController alloc] initWithNibName:#"AnotherViewController" bundle:nil];
detailViewController.delegate = self;
[self.navigationController pushViewController:detailViewController animated:YES];