Issue Passing Values From One View Controller To Another - ios

I am trying to take the text that is typed into UITextFields in one view, and pass those values into a different View Controller when a button is pressed. In the first view controller (CreateViewController) I have:
#import <UIKit/UIKit.h>
#import <MessageUI/MFMailComposeViewController.h>
#class ThePreviewViewController;
#interface CreateViewController : UIViewController <UIAlertViewDelegate, MFMailComposeViewControllerDelegate> {
UIDatePicker *datePicker;
UIDatePicker *datePicker2;
ThePreviewViewController *_thePreview;
}
#property (nonatomic, retain) IBOutlet UITextField *toName;
#property (nonatomic, retain) IBOutlet UITextField *fromName;
#property (nonatomic, retain) IBOutlet UITextField *issue;
#property (nonatomic, retain) ThePreviewViewController *thePreview;
#property (nonatomic, retain) IBOutlet UITextField *expire;
#property (nonatomic, retain) IBOutlet UITextField *loveMessage;
#property (nonatomic, retain) IBOutlet UITextField *gift;
-(IBAction)build;
#end
The implementation file is:
#import "ThePreviewViewController.h"
#implementation CreateViewController
#synthesize toName, fromName, gift, loveMessage, issue, expire, datePicker, datePicker2;
#synthesize thePreview = _thePreview;
-(IBAction)preview {
if (_thePreview == nil) {
self.thePreview = [[ThePreviewViewController alloc] initWithNibName:#"ThePreviewViewController" bundle:[NSBundle mainBundle]] ;
}
_thePreview.issue.text = issue.text;
_thePreview.gift.text = gift.text;
_thePreview.expire.text = expire.text;
[self.navigationController pushViewController:_thePreview animated:YES];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
However, after I connect all the outlets, the labels in ThePreviewViewController stay at null. Thoughts?

It looks like this is due to an issue which has been discussed here before: when you instantiate your ThePreviewViewController its UIKit instances are not yet available to have their properties set.
The solution is to create and set NSString properties on your ThePreviewViewController (or more compactly use an NSDictionary) which then use, in its ViewWillAppear event handler to set the properties of its UIKit elements.

Instead of setting UITextField text in ThePreview VC, you should set a NSString property. This is because the UITextField might not have been loaded yet and _thePreview.issue.text = issue.text, will have no effect, since _thePreview.issue has still not been created. So create a property (eg. NSString *issueString) in your ThePreview VC and then set that property as _thePreview.issueString = issue.text in your CreateViewController, and then finally in your ThePreview VC set your textField text in your viewDidLoad method using self.issue.text = self.issueString;
Hope this helps.

Related

After converting to ARC I am getting "message sent to deallocated instance"

I am creatinng an instance of a View like this...
- (IBAction)findPatientTapped:(id)sender {
RequestDialogViewController *findPatientViewController = [[RequestDialogViewController alloc] initWithNibName:#"RequestDialogViewController" bundle:nil];
findPatientViewController.delegate = self;
findPatientViewController.autoCorrectOff = YES;
findPatientViewController.defaultResponse = #"";
findPatientViewController.keyboardType = #"ASCII";
findPatientViewController.returnKeyType = #"Go";
findPatientViewController.tag = findRequestTag;
findPatientViewController.editSet = YES;
findPatientViewController.titleText = #"Find Patient";
findPatientViewController.messageText =#"Enter all or a portion of the patient's name...";
findPatientViewController.messageText2 = #"Last Name...";
findPatientViewController.messageText3 = #"First Name...";
findPatientViewController.showResponse2 = YES;
findPatientViewController.showNavBarSaveButton = NO;
findPatientViewController.infoTextFile = #"";
findPatientViewController.view.frame = CGRectMake(280, 230, 480, 300);
[self.view addSubview:findPatientViewController.view];
}
The view contains 2 UITextField fields for entry by the user. This all worked fine before running the convert to ARC tool. After the conversion the view crashes when trying to enter a value in either of the 2 fields with...
-[RequestDialogViewController respondsToSelector:]: message sent to deallocated instance
Here is the .h file of the UIViewController after running the conversion to ARC tool...
#import <UIKit/UIKit.h>
#protocol RequestDialogViewControllerDelegate;
#interface RequestDialogViewController : UIViewController <UITextFieldDelegate>{
id<RequestDialogViewControllerDelegate> __weak delegate;
IBOutlet UINavigationBar *navBar;
IBOutlet UITextField *response;
IBOutlet UITextField *response2;
IBOutlet UILabel *message;
IBOutlet UILabel *message2;
IBOutlet UILabel *message3;
IBOutlet UIButton *saveButton;
NSTimer *selectAllTimer;
NSString *defaultResponse;
NSString *titleText, *infoTextFile;
NSString *messageText, *messageText2, *messageText3;
NSString *placeHolderText;
NSString *keyboardType, *returnKeyType;
BOOL editSet, showSaveButton,showNavBarSaveButton, showResponse2, autoCorrectOff;
int tag;
}
#property (weak) id<RequestDialogViewControllerDelegate> delegate;
#property (nonatomic, strong)IBOutlet UITextField *response;
#property (nonatomic, strong) IBOutlet UITextField *response2;
#property (nonatomic, strong)IBOutlet UILabel *message;
#property (nonatomic, strong)IBOutlet UILabel *message2;
#property (nonatomic, strong) IBOutlet UILabel *message3;
#property (nonatomic, strong)IBOutlet UIButton *saveButton;
#property (nonatomic, strong)NSString *defaultResponse;
#property (nonatomic, strong)NSString *titleText, *infoTextFile;
#property (nonatomic, strong)NSString *messageText, *messageText2, *messageText3;
#property (nonatomic, strong)NSString *placeHolderText;
#property (nonatomic, strong)NSString *keyboardType, *returnKeyType;
#property (nonatomic, strong)IBOutlet UINavigationBar *navBar;
#property (readwrite)BOOL editSet, showSaveButton, showNavBarSaveButton, showResponse2, autoCorrectOff;
#property (readwrite)int tag;
#property (nonatomic, strong) NSTimer *selectAllTimer;
- (IBAction)saveButtonPressed:(id)sender;
- (void)selectAll;
- (IBAction)editingDidEnd:(id)sender;
#end
#protocol RequestDialogViewControllerDelegate <NSObject>
#optional
- (void)requestDialogViewDidDismiss:(RequestDialogViewController *)controller withResponse:(NSString*)reqResponse response2:(NSString*)reqResponse2;
#end
Here is the pertenant references in the .h file of the class creating the instance of the RequestDialog view...
#import "RequestDialogViewController.h"
#interface OrthoViewController : UIViewController <RequestDialogViewControllerDelegate>{
}
- (void)requestDialogViewDidDismiss:(RequestDialogViewController *)controller withResponse:(NSString*)reqResponse response2:(NSString*)reqResponse2;
#end
What do I need to do to make this work under ARC? I am thinking it might have something to do with how the protocol is formed.
Thanks,
John
**** Thanks to Dan I resolved this by making findPatientViewController a property of the calling class...
RequestDialogViewController *findPatientViewController;
#implementation OrthoViewController
- (IBAction)findPatientTapped:(id)sender {
findPatientViewController = [[RequestDialogViewController alloc] initWithNibName:#"RequestDialogViewController" bundle:nil];
//set all the properties and add the subview
}
#end
Your findPatientViewController has nothing retaining it, so it gets deallocated at the end of the method where you create it. Then, when something in it's view tries to call a delegate method on it you get that crash.
If findPatientTapped is a method in a view controller then you should add the findPatientViewController as a child view controller. If it's in a view, then you need to least store the findPatientViewController in a property so it doesn't get deallocated while you are still using it.
Your code didn't really work properly before ARC, you just had a memory leak.

Cannot assign to view controller's property after instantiating from storyboard

I'm instantiating a view controller from the storyboard with this code:
CalloutViewController *calloutVC = (CalloutViewController *)[self.storyboard instantiateViewControllerWithIdentifier:#"CalloutViewController"];
and trying to assign to it's property nameLabel, declared here in its header:
#interface CalloutViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *nameLabel;
...
#end
using
calloutVC.nameLabel.text = #"test";
However, after the assignment, the property is still nil.
It's because the IBOutlet is not loaded yet. You need to create a NSString property and assign your value to it. And in your CalloutViewController's viewDidLoad assign the value to your IBOutlet.
Like:
#interface CalloutViewController : UIViewController
#property (nonatomic, weak) IBOutlet UILabel *nameLabel;
#property (nonatomic, copy) NSString *nameValue;
...
#end
And in your viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
self.nameLabel.text = self.nameValue;
...
}
And assign the property like:
calloutVC.nameValue = #"test";

UILabel text property iOS

I would like to modify the text property of a UILabel (nameLbl) but don't know what i am wrong.
I have 2 Views, the first is a ViewController, the second is ProfileViewController. The ProfileViewController fill some field of user profile this data are passed to ViewController and showed in UIlabel.
The issue is I can't show the datas in the ViewController.
What am I get wrong?
---ViewController.h---
#interface ViewController : UIViewController
{
IBOutlet ViewController *profile;
IBOutlet UILabel *nameLbl, *celLbl, *cfLbl;
IBOutlet UITextField *nameTF;
}
#property (nonatomic, retain) IBOutlet ViewController *profile;
#property (retain, nonatomic) IBOutlet UILabel *nameLbl, *celLbl, *cfLbl;
#property (nonatomic, retain) IBOutlet UITextField *nameTF;
-(void) setUser: (NSString *) name:(NSString *) cel:(NSString *) cf;
#end
---ViewController.m---
#synthesize nameLbl, celLbl, cfLbl;
-(void) setUser:(NSString *)name:(NSString *)cel:(NSString *)cf
{
nameLbl = [[UILabel alloc] init];
[nameLbl setText:name];
}
this is the connection inspector
https://drive.google.com/file/d/0Bz7WcQmZNuFLMWt3QUo1Tk5XUW8/edit?usp=sharing
Remove
nameLbl = [[UILabel alloc] init];
from your code it seems that the nameLbl UILabel has already been initialized from nib, and you are creating a new memory reference, so its not working.

How to save UITextField Text to NSString?

In my main view controller, I have a UITextField, and I am trying to save the text input into it to a NSString in my Homework model(class).
Homework.h
#import <Foundation/Foundation.h>
#interface Homework : NSObject
#property (nonatomic, strong) NSString *className;
#property (nonatomic, strong) NSString *assignmentTitle;
#end
Homework.m
#import "Homework.h"
#implementation Homework
#synthesize className = _className;
#synthesize assignmentTitle = _assignmentTitle;
#end
In my assignmentViewController, I create an object of type Homework and try to set it equal to whatever is entered into the the UITextField when the Save Button is pressed.
Assignment View Controller
#import <UIKit/UIKit.h>
#import "Homework.h"
#interface Assignment : UIViewController {
}
#property(nonatomic) IBOutlet UITextField *ClassNameField;
#property(nonatomic) IBOutlet UILabel *ClassNameLabel;
#property (weak, nonatomic) IBOutlet UIButton *SaveButton;
#property (nonatomic, strong) Homework *homeworkAssignment;
- (IBAction)Save:(UIButton *)sender;
#end
AssignmentViewController.m
- (IBAction)Save:(UIButton *)sender {
self.homeworkAssignment.className = self.ClassNameField.text;
NSLog(#"SaveButtonPressed %#", self.homeworkAssignment.className);
}
The NSLog prints out that className is (null). Can anyone help me figure out what I am doing wrong? This is my first ever iOS app (besides Hello World).
Edit: This is using ARC
Edit: I tried changing
self.homeworkAssignment.className = self.ClassNameField.text; to
self.homeworkAssignment.className = #"TEST";
and the log still shows (Null).
Double check you properly linked ClassNameField outlet and that you're initializing homeworkAssignment. Something like.-
self.homeworkAssignment = [[Homework alloc] init];
By the way, you should consider using camelCase notation for your variable names :)
Well to be honest the first steps are always hard but you should learn it the right way, héhé
First of all synthesize this way:
#synthesize labelAssignmentTitle,labelClassName;
or
#synthesize labelAssignmentTitle;
#synthesize labelClassName;
there is no need to do the following:
#synthesize className = _className;
#synthesize assignmentTitle = _assignmentTitle;
Now if you initialize the right way from the the start you'll find it a lot easier later!
HomeWork.h
#interface HomeWork : NSObject
#property (nonatomic, strong) NSString *className;
#property (nonatomic, strong) NSString *assignmentTitle;
-(id)initWithClassName:(NSString *)newClassName andAssignmentTitle:(NSString*)newAssigmentTitle;
HomeWork.m
#implementation HomeWork
#synthesize assignmentTitle,className;
-(id)initWithClassName:(NSString *)newClassName andAssignmentTitle:(NSString*)newAssigmentTitle {
self = [super init];
if(self){
assignmentTitle = newAssigmentTitle;
className = newClass;
}
return self;
}
#end
ViewController.m
- (IBAction)saveIt:(id)sender {
HomeWork *newHomeWork = [[HomeWork alloc]initWithClassName:[labelClassName text]andAssignmentTitle:[labelAssignmentTitle text]];
}
Because of this, you directly make a newHomeWork object with the parameters given by your two UITextFields.
Now print it out in your logmessage and see what happends ;)

Access an IBOutlet from another class?

I need to access this IBOutlet's value in another class.. How would I go about doing this?
Heres my SaveTextViewController.h class
#import <UIKit/UIKit.h>
#interface SaveTextViewController : UIViewController{
IBOutlet UITextField *saveText;
}
#property (retain, nonatomic) IBOutlet UITextField *saveText;
#end
And here is my TextView.m class
#import "TextView.h"
#import "SaveTextViewController.h"
#implementation TextView
- (IBAction)saveTextView{
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [documentPaths objectAtIndex:0];
//Trying to access the returned variable "saveText" from IBOutlet in SaveTextViewController
NSString *documentTXTPath = [documentsDirectory stringByAppendingPathComponent:#"%d",saveText];
NSString *savedString = self.text;
[savedString writeToFile:documentTXTPath atomically:YES];
NSLog(#"%#", documentTXTPath);
}
Thanks!
There is no clean way to just generically access the IBOutlet UITextField *saveText from any app. You can declare it in the .h file instead of the .m and have it accessible that way, assuming you can send a pointer to your SaveTextViewController class. But its a better practice to pass a pointer to your UITextFIeld to your TextView class from your SaveTextController class.
in TextView.h create a property
#interface TextView: UIView
#property (nonatomic, strong) UITextField *textField;
#end
in your SaveTextViewController.m create another property:
#interface SaveTextViewController : UIViewController{
IBOutlet UITextField *saveText;
}
#property (retain, nonatomic) TextView *textView;
#property (retain, nonatomic) IBOutlet UITextField *saveText;
assign self.textView to your TextView
in your viewDidLoad method, set the textField in your TextView class like this:
self.textView.textField = self.saveText;
That would give you a clean connection between those two classes.
An IBOutlet is just behaving like any other property or instance variable. So if you want to pass that reference to another class, just do exactly that. Note that you do not need to specify an instance variable with the same name as the property. The current runtime will handle this itself.
If you want to pass a reference to the UITextField, add a property to your text view.
#interface TextView : UIView
#property (retain, nonatomic) UITextField *saveTextField;
...
#end
In your SaveTextViewController you can now set that property. You can do this in the viewWillAppear: method for example.
#implementation SaveTextViewController
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.textView.saveTextField = self.saveText
}
#end
Also note that if you need a reference to the TextView and you created that in your nib/storyboard, add another IBOutlet to the SaveTextViewController.
#import "TextView.h"
#interface SaveTextViewController : UIViewController
#property (retain, nonatomic) IBOutlet UITextField *saveText;
#property (retain, nonatomic) IBOutlet TextView *textView;
#end
Finally I would also recommend you to rename saveText to saveTextField, because that's what it is. Also, you seem to be using unsanitized user input data from text fields and feed them into filenames. This is generally a bad idea™. I would recommend you to think about what you are actually trying to do. This is potentially dangerous and can lead to data loss and more fun stuff.
In
#implementation TextView
type
SaveTextViewController *saveTextViewController = [[SaveTextViewController alloc] init];
NSString *documentTXTPath = [documentsDirectory stringByAppendingPathComponent:#"%d",saveTextViewController.saveText];
Hope this helps!

Resources