Pass UITextView contents to ModalViewController from parent view - iphone

I have a view with a UITextView and a button, both connected via an IBOutlet. Pressing the button brings up a ModalViewController. I need to pass the text in the UITextView to the ModalViewController as a string. I've done a bit of Googling but could only find info on passing strings from the ModalViewController to the parent view.
PS: Forgive my newbieness :p

Is the ModalViewController object created and presented in an IBAction method? If so, in that method you should query the UITextView for its value (textView.text) and pass it to the ModalViewController.

You could subclass init with nib:bundle to include a string for the mycontroller view controller. So that in it's .h you will have
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil andstring:(NSString *)string;
and in the viewcontroller's .m you will have
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil andstring:(NSString *)string
{
//initialize self here from bundle;
//do other stuff
self.text=string}
assuming you define a NSString *text propery in the header of the view controller which you present modally;
Then in where you define my controller you would do
MYVCController *mycontroller=[[MYVCController alloc] initWithNibName:nibname bundle:bundlename andstring:textView.text];

Either you need to create a property for setting a variable inside the modal view controller, or you can define a method and do that.
e.g.
#interface ModalViewController : UIViewController {
NSString *displaystr;
}
#property (nonatomic, retain) NSString *displaystr;
...
#end
#implementation ModalViewController
#synthesize displaystr;
...
#end
Then you can use the property displaystr to store the text in the UITextField. You can get the text via the text property.

Make a NSString varible in appDelgate class and make it property.
NSString *value;
#property(nonatomic,retain) NSString *value;
and synthesize it in .m
#synthesize value;
Make object for you app delegate class and access that to set that value and get that value.
in modelViewController
write this code for button which you use to dismiss
yourAppDelegateClass *objDelegate=(yourAppDelegate *)[[UIApplication sharedApplication] delegate];
objDelegate.value=textView.text;
and by the object of app delegate you can access the value.

Related

How to send data from UItextfields of one viewcontroller to new view controller? [duplicate]

I am a bit stuck on trying to pass data from two UITextfields on one viewcontroller to another viewcontroller. Basically I got the items below:
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
IBOutlet UITextfield *Textfield1;
IBOutlet UITextfield *Textfield2;
}
-(IBAction)GoNextView:(id)sender;
#end
ViewController.m
#interface ViewController ()
#end
#implementation ViewController
(IBAction)GoNextView:(id)sender {
SecondView *second = [[SecondView alloc] initWithNibName:nil bundle:nil];
[self presentViewController:second animated:YES completion:NULL];
}
- (void)viewDidLoad {
[super viewDidLoad];
}
SecondView.h
#import <UIKit/UIKit.h>
#interface SecondView : UIViewController {
IBOutlet UILabel *ShowTextfield1;
IBOutlet UILabel *ShowTextfield2;
}
-(IBAction)GoBack:(id)sender;
#end
SecondView.m
#interface SecondView ()
#end
#implementation SecondView
- (IBAction)GoBack:(id)sender {
[self dismissViewControllerAnimated:YES completion:NULL];
}
What I want is, that when the button GoNextView is pressed it should pass the data in the UITextfield to the SecondView. And the go to the next page. The data should now be displayed in the two Labels on the SecondView. I've been struggling with this for many hours now and its killing me. I know I have to use some NSString and #property(nonatomic, retain) NSString *asdas. But I simply can't make it work. So based on the above code how do I pass data from the two UITextfield to the two labels on the next view?
Instead of navigating to the second view through a function, use Storyboard Segues. Create a storybaord application. To Create a segue you need a navigation view controller. You can do that by the following steps.
Select the first view controller and go to Editor -> Embed In -> Navigation Controller.
Then Ctrl+Click on the "GoNextView" button, and drag and drop in the SecondView.
You will get three options: push, model, custom. Click push then a segue will be created between these two views.
Click that segue and click the "Show the Attribute Inspector" on the right side property window. Now name it as "connector" or which ever name you prefer.
Now, in SecondView.h create two strings,
#property (nonatomic, retain) NSString *str1;
#property (nonatomic, retain) NSString *str2;
and synthesize them in SecondView.m.
Lets name your UITextFields as "text1" and "text2" which are in your ViewController. Go to the ViewController.h and add #import "SecondView.h"
In ViewController.m do the following,
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"connector"])
{
ViewController *VC = [segue destinationViewController];
VC.str1 = text1.text;
VC.str2 = text2.text;
}
}
Now you can display these strings in your SecondView. In Secondview.m,
label.text = str1;
and it will be displayed.
Use NSUserDefaults or the normal synthesising common interface variables. For example,
NSUserDefaults
From sender's view controller,
NSString *text=textField1.text;
NSUserDefaults *prefs=[NSUserDefaults standardUserDefaults];
[prefs setObject:text forKey:#"text1value"];
And you can get the value from any view controller as,
NSUserDefaults *prefs=[NSUserDefaults standardUserDefaults];
NSString *received string= [prefs stringForKey:#"text1value"];
Normal assigners,
I believe you must be using performsegue to navigate view controllers. There is a delegate method called "prepareforsegue" and you can assign the textfield values into the interface variables. For example,
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"seguename"]) {
destViewController *destViewController = segue.destinationViewController;
destViewController.name = #"some text";
}
}
In the receiver's view controller, getter variable is actually defined as,
In .h file, #property(nonatomic, strong) NSString *name;
In .m file, Don't forget to synthesis the variable after implementation
#implementation destViewController
#synthesize name;
Hope it helps!

IBOutlet UITextView is nil after calling another class initWithNibName and back to the class using method

My problem is that in ProductNote class UIButton Action I did initWithNibName Notes Class to show the popOver with a UITableView in Notes Class. I am fetching data from sqlite and then load it to UITableView in tableViewDidSelectRowAtindexPath:. I got the selectedNote and creates object of ProductNote Class to call selectedNote instance method that only set IBOutlet's textview.text but its nil. Thats my problem, Below is the code please help me to knowing why i face this type of issue. I am using Xcode 4.3.3 and not using ARC. Manually I defined dealloc method on every ViewController
//**ProductNote.h Class****************************
#import <UIKit/UIKit.h>
#class Notes;
#interface ProductNote : UIViewController<UIPopoverControllerDelegate>
{
UIPopoverController *popOverController;
UITextView *txtmesssagenotes;
Notes *objNotes;
}
#property (retain, nonatomic) IBOutlet UITextView *txtmesssagenotes; //It is Connected to ProductNote.xib
#property (retain,nonatomic) UIPopoverController *popOverController;
#property (retain,nonatomic) Notes *objNotes;
-(IBAction)presentPopOver:(UIButton*)sender;
-(void)selectedNote:(NSString*)note;
#end
//ProductNote.m Class
#implementation ProductNote
#synthesize txtmesssagenotes,popOverController,objNotes;
-(IBAction)presentPopOver:(UIButton*)sender
{
self.objNotes=[[Notes alloc]initWithNibName:#"Notes"bundle:nil];
UIPopoverController *popOver=[[[UIPopoverController alloc]initWithContentViewController:objNotes]autorelease];
self.popOverController=popOver;
self.popOverController.delegate=self;
self.popOverController.popoverContentSize=objNotes.view.frame.size;
CGRect rect=[self.view convertRect:objNotes.view.frame fromView:self.view];
rect.origin.y+=110;
rect.origin.x+=23;
[self.popOverController presentPopoverFromRect:rect inView:self.view permittedArrowDirections:0 animated:YES];
//Then I get popOver with tableview
}
-(void)selectedNote:(NSString*)note
{
self.txtmesssagenotes.text=note;
//Here I am getting txtmesssagenotes=0X0 or nil. Using self or without self Please tell me the reason.
}
- (void)dealloc {
[txtmesssagenotes release];
[popOverController release];
[objNotes release];
[super dealloc];
}
#end
#interface Notes : UITableViewController
{
NSMutableArray *arrNotes;
NSString *selectedNote;
UITableView *tblNotes;
}
#property(nonatomic,retain)NSMutableArray *arrNotes;
#property(nonatomic,retain)NSString *selectedNote;
#property(nonatomic,retain)IBOutlet UITableView *tblNotes;
#end
//Actually I skip the other methods that makes larger program to read . other methods only used to fetch data from sqlite and fill up the arrNotes that is used to fill all rows in the tableview.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedNote=[self.arrNotes objectAtIndex:indexPath.row];
//Here self.arrNotes valid object and contains the data, and assigns NSString object to self.selectedNote
ProductNote *productNote=[[ProductNote alloc]init];
[productNote selectedNote:self.selectedNote]; //after calling selectedNote i goto to selectedNote implementation or definition above.
[productNote release];
}
-(void)dealloc
{
[arrNotes release];
[selectedNote release];
[tblNotes release];
[super dealloc];
}
It is because just as you stated that txtmesssagenotes was created using IB. And you never presented your ProductNote UIViewController instant productNote. So the txtmesssagenotes was never allocated and initialized properly.
Are you calling selectedNote: before your view has loaded?
Just because you created a view controller with a xib doesn't mean that it loads all your subviews immediately.
The xib is parsed and all your views are created the first time that the view controller's view property is asked for - this is usually just before it appears for the first time.
Until then, all the IBOutlet connections will be nil.
You need to store the text for your note as an NSString property of you view controller. Then, inside either viewDidLoad you need to call self.txtmesssagenotes.text=self.note; - viewDidLoad is automatically called just after your view is loaded so you are guaranteed to have all your IBOutlets set by then.
You shouldn't rely on your view objects to store the state of your app (in this case, the text of the note). If a low memory warning is received while your view controller isn't visible then all your view objects will be deleted - they will only be recreated when your view controller becomes visible again - if you are storing your note string inside a UITextView then it might no be there the next time you ask for it :) You should always store data in a property of your view controller (or somewhere else you control) and create your views using it.

How to copy text from one ViewController to another?

I'm writing a little quiz application. So I have a first view, where I ask a person to enter his/her name and a button which is the IBAction to go the next view with the first question. In the end, after a person has answered all questions, comes the congratulations view, where I want to copy the name, that was entered on the first view. Say there will be a phrase "Well done, John!" How can I do it?
On the first view(FirstViewController) I made a textfield
IBOutlet UITextField *text1;
And on the last view in .h:
IBOutlet UITextField *text2;
and
-(IBAction)copy:(id)sender;
And in .m:
- (IBAction)copy:(id)sender
{
[text2 setText:[text1 text]];
}
and
#import "FirstViewController.h"
But it says identifier text1 is undefined
I don't know what else to do...
You can override the
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
method of last view controller with something like:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil andUserName:(NSString*)userName
(don't forget to declare this method in your .h file.)
Now while initializing your last view controller, you can pass the name of the user to last view controller.
In the implementation of the this overriden method in last view controller, copy this name in some local variable. and use it.
Hope this will solve your problem.
In your firstView add NSString with its property
Something like this in .h file
NSString *username;
and
#property (nonatomic , retain) NSString *username;
in .m file
username = text1.text;
In LastView
im .m file
#import "FirstView.h"
And where ever you want username try this
FirstView *firstview = [[FirstView alloc] init];
text2 = firstview.username;
Hope it works..!!
Override the init method of SecondViewController as follows
-(id)initWithUsername:(NSString *)username
{
//create instance and then do
text2.text = username ;
}
And in the FirstViewController , where you create the instance of SecondViewController init it using the above
SecondViewController *second = [[SecondViewController alloc] initWithUsername:text1.text];
For passing value from one VC to other you have to do following code :
First declare local variable in next view where you want to move like.
#property(nonatomic, strong) NSString *personName;
Now prepare object of second VC in the first VC.m file on button click action. But before that must set storyboard identifier of that second VC in storyboard.
SecondViewController *obj = (SecondViewController *) [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
obj.personName = self.txtUserName.text;
Now go on there on second VC and do whatever you want.
Note : Here you don't need to used userdefaults, OR prepared init methods with parameters, OR using delegates etc.
The best way to do this would be taking the variables you need on various views and handling them on the delegate since the delegate has access to everything. Making a Global variable is never advisable that is what the delegate is for.
You can refer to this question that treats the same issue: Passing data between view controllers
You can add a NSString member (along with a property) in the application delegate class.
/// AppDelegate.h, or whatever it's called in your application
#interface AppDelegate : NSObject <UIApplicationDelegate> {
NSString *username;
// <rest of the members>
}
...
#property (nonatomic, retain) NSString *username;
#end
/// AppDelegate.m
#implementation AppDelegate
#synthesize username;
#end
/// FirstViewController.m
-(void)viewDidDissappear:(BOOL)animated{
[super viewDidDissappear:animated];
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.username = text1.text;
}
/// LastViewController.m (or whatever it's called)
-(void)viewDidLoad{
[super viewDidLoad];
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[text2 setText:[NSString stringWithFormat:#"Well done %#", appDelegate.username]];
}
Ok, so for everyone to be happy, you can (and are suggested to) create your own singleton class in which you can hold non-persistent global variables, and use in the code above instead of the application delegate.
/// SharedData.h
#interface SharedData: NSObject {
NSString *username; /// or instead you can have a NSMutableDictionary to hold all shared variables at different keys
}
+(SharedData *)sharedInstance;
#property(nonatomic, retain) NSString *username;
#end
/// SharedData.m
#include "SharedData.h"
static SharedData *_sharedInstance=nil;
#implementation SharedData
#synthesize username;
+(SharedData)sharedInstance{
if(!_sharedInstance){
_sharedInstance = [[SharedData alloc] init];
}
return _sharedInstance;
}
#end
I would make use of NSUserDefaults to set the user's name when they enter it. Then, in your last view controller, just query NSUserDefaults again for the name you want. Granted, this is still global state, but NSUserDefaults is meant for this sort of purpose:
// In the first view controller
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:#"John Doe" forKey:#"XXUserNameKey"]; // This should actually be an extern for your app to use globally
// In the last view controller
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSString *userName = [userDefaults stringForKey:#"XXUserNameKey"];
Adding state to your app delegate is an abuse of the design pattern.
Also, I should clarify that NSUserDefaults should not be used as a general-purpose storage container. Its intent is for common, shared data like user names, preferences, etc. Something like the name a user enters at the beginning of a game seems to fall within the usage pattern.

pass data from mainView to a subview

I am building a utility-based application, the data is stored in the MainViewController, and now I know how to pass data to the FlipsideViewController (many regards to this thread BTW, Sending data from Mainview to Flipside?). But I am getting the data onto an subview (subclass of UIView) that I have added to the flipside view. How can I pass data to this subview? I saw there is already a delegate and protocol set up in the FlipsideViewController.h, I am really new to the delegate sort of things. Any help would be greatly appreciated!
Updates:
On the main view, I have a couple of text fields for users to input to create an object. All the objects are stored in an array. Namely, my data is created and stored in the MainViewController. Now on the flip side, I have a custom UIView subclass which allows me to do my own drawing based on the data in that array. What I need to do here is pass the data that stored in MainViewController to this subview. Here is my relevant code:
In the MainViewController.m
- (IBAction)showInfo:(id)sender {
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:#"FlipsideView" bundle:nil];
controller.delegate = self;
controller.receiver = data;//this is what I've done.
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
[controller release];
}
In the FlipsideViewController.h
#protocol FlipsideViewControllerDelegate;
#interface FlipsideViewController : UIViewController {
id <FlipsideViewControllerDelegate> delegate;
DataModel *receiver; //create a property to receive the data transferred from main view
}
#property (nonatomic, assign) id <FlipsideViewControllerDelegate> delegate;
#property (nonatomic, retain) DataModel *receiver;
- (IBAction)done:(id)sender;
#end
#protocol FlipsideViewControllerDelegate
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller;
#end
In the above code, "data" is an DataModel object declared in the MainViewController.h file.
And I want to do my custom drawing in drawing class (subclass of UIView), how can I pass data from the FlipsideViewControllerto this subview? Do I need to make use of delegate declared in the FlipsideViewController.h file? Thanks in advance!
I have had a quick look at the template and think you are getting confused with what the delegate is being used for.
The delegate in this template is not transferring data. When you have clicked the done button it calls back to MainViewController and asks it to call the dismissModalViewControllerAnimated method so that it can remove the view controller. This seems a bit superflous as the documentation states
If you call this method on the modal view controller itself, however, the modal view controller automatically forwards the message to its parent view controller.
Therefore you don't really need to call the parent to do this.
In Interface builder you can see that the FlipsideView.xib has it's File's Owner set to FlipsideViewController.xib.
Now if you right click the File's Owner you will see that view is connected to View this basically means that view is the name of the property in FlipsideViewController and View is the element in Interface Builder.
Therefore we can access elements in the xib file from FlipsideViewController using outlets.
To say draw a label you will need to do a couple of things
First add a property in the .h and synthesize it in the .m like
// FlipsideViewController.h
#interface FlipsideViewController : UIViewController
#property (nonatomic, retain) IBOutlet UILabel *testLabel; // <----- Added this
#property (nonatomic, assign) id <FlipsideViewControllerDelegate> delegate;
- (IBAction)done:(id)sender;
#end
// FlipsideViewController.m
#implementation FlipsideViewController
#synthesize delegate = _delegate;
#synthesize testLabel = _testLabel; // <----- Added this
// More methods
- (void)dealloc
{
[_testLabel release]; // Always do you memory management
[super dealloc];
}
Then back in Interface Builder
Add a UILabel element to your view
ctrl + drag from File's Owner to the UILabel you added
Select the label in my example it is testLabel
Now these are hooked up correctly. The place where you want to be setting the value of the label is in viewDidLoad: which you can now do like this
- (void)viewDidLoad
{
[super viewDidLoad];
self.testLabel.text = #"It Works"; // You would use the data passed in from `MainViewController`
}
I find the easiest way to pass data from one view to another is by directly setting the data in the next view from the original view.
For example;
In your FlipsideViewController.h, declare a 'container' for the data you want to pass. It must be the same class on both sides to work properly, ie. NSArray to NSArray, NSMutableDictionary to NSMutableDictionary.
NSMutableArray *newData;
...
#property (nonatomic, retain) NSMutableArray *newData; // This allows you to access this object from outside this class.
and in FlipsideViewController.m
#synthesize newData;
...
[newData release];
Now we need to pass the data, so to speak. Let's say the data we want to 'send' is stored in a NSMutableArray called 'results'.
In our MainViewController.m, when we are instantiating our next view controller (in this case FlipsideViewController) we can directly reference the newData mutable array after we initalize the nib.
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:#"FlipsideView" bundle:nil];
controller.newData = results;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
[controller release];
Make sure you are importing your FlipsideViewController in your MainViewController.h file.
If the property is declared in your .h file, you can pretty much reference the contents of the object from anywhere within the view stack!
Hope that helps :D

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.