Set Text Field from another object ios - objective-c

I am stuck trying to set and retrieve the text in a UITextField object on titleViewController.
I have a Journal object that has a reference to the titleViewController object, but I can not seem to set the text value for the UITextField.
I have an outlet to the UITextField object in the titleViewController, and Journal can see it, but when I write to code to set the value nothing happens when it is run.
There is no errors that pop up in XCode or the Log. I know it should work as the set up works for accessing custom methods in other such viewControllers being managed by the same Journal.
-EDIT-
Here is a code sample as requested:
//Get viewController from Array
TitleVC *titlePage = [_PageArray objectAtIndex:0];
//Get string from Dictionary
NSString *test = [_saveDictionary objectForKey:#"Name"];
//This is one of the attempts to set the UITextField
//FIXED by Tomy211(but still does not work)
[titlePage.textName setText:test];
//This is attempting dot notation
titlePage.textName.text = test
titlePage.textName = test //Wrong I know but had to test
//Also made sure test was a proper string
NSLog(test) //Displayed "Dan" as Expected
This is in Journal.m which accessed a reference to the titleVC from a storyboard using this code:
-(UIViewController *)loadView:(NSString *)viewID{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:viewID];
return viewController;
}
The ViewController returned from that method is used in displaying the View in a scrollview, and I havent had an issue with accessing methods from the ViewControllers this way.
All I want to do is let Journal.m set and read the value from textName which is an outlet connected to a UITextField.
-UPDATE-
I checked and discovered I can read the value of the textField but not write to it.
-FINAL UPDATE-
I found the issue with my code. The code was correct(minus the correction by Tomy211), but the issue was where I was calling the code. I was calling the method before the view was displayed, so when the view did get displayed it revert back to the default values.
Note to all that have similar issues:
Check to make sure the view is being displayed before updating a value of a UIObject part of the view. If you have to update values with the view not displayed, use instance variables and have the UIObject get their values from them on the viewDidLoad method.

The problem was I tried to update the TextField objects before the view has been loaded.
Moving the method call to after the point I load the view fixes the problem. I have updated my question to reflect what was correct, and what was incorrect.
Note to all that have similar issues: Check to make sure the view is being displayed before updating a value of a UIObject part of the view. If you have to update values with the view not displayed, use instance variables and have the UIObject get their values from them on the viewDidLoad method.

Related

xCode pass data between dynamically created ViewControllers

I am trying to set up a project which dynamically creates ViewControllers based off a JSON file. I asked a question the other day about how to create this here
xCode Dynamically create ViewControllers
So I have been able to create the ViewControllers dynamically and after playing around with it more, I have been quite easily set it up so when the app loads, it generates how ever many numbers of ViewControllers is specified in the JSON. I can also navigate between them easy enough and also have each screen set up buttons, views etc from the JSON. I do this simply by doing
NSDictionary *MainJSON = [sJson JSONValue];
NSArray *theArray = [MainJSON valueForKey:#"viewControllers"];
Then loop through theArray creating a ViewController instance.
My problem is, I want to be able to pass data between the ViewControllers. So say for example I set it up in the JSON so the first ViewController has a text field. The user will enter some data and I want to be able to set it up so when they navigate to the next screen, that data is carried to the next screen. I currently switch screens like this
-(void)nextScreen
{
for(int i = 0; i < [vcArray count]; i++)
{
int iID = i+1;
if([self.navigationController.viewControllers count] == iID)
{
ViewController *theVC = [vcArray objectAtIndex:i];
[self.navigationController pushViewController:theVC animated:YES];
break;
}
}
}
Now usually each ViewController would have a class, so in the ViewController I am pushing I can do property and synthesise a NSString in that class, so when passing data to the next ViewController, I would just do this.
vc.theString = textField.text
But as I am dynamically generating these ViewControllers, I can't do this as I am only using one .h and .m file and each ViewController I generate is using the same XIB file. Does anyone have any ideas of how I could go about passing data in this set up?
If your problem is that you need different xib for same view controller, you can supply all of them in the main iOS app, later by passing xib name in JSON you can instantiate that xib and assign to the controller.
If you also need to recall UIView objects you don't know by name, you can always use the tag attribute stored in JSON as well.
Maybe you can also store the UIView type, such as 'UILabel', 'UITextView', ecc... and call appropriate setter for value.
Figured it out. If I give each view a tag from the JSON, can easily connect up the objects I need.

Replacing Storyboard Segue with pushViewController causes strange behaviour

I can't seem to figure this out for the life of me. I have a custom table view cell, in that cell I have a few buttons configured. Each button connects to other view controllers via a storyboard segue. I've recently removed these segues and put a pushViewController method in place. Transition back and forth across the various views works as expected however the destination view controller is not displaying anything! I have some code below as an example.
Buttons have this method set:
[cell.spotButton1 addTarget:self action:#selector(showSpotDetails:) forControlEvents:UIControlEventTouchUpInside];
// etc...
[cell.spotButton4 addTarget:self action:#selector(showSpotDetails:) forControlEvents:UIControlEventTouchUpInside];
// etc...
showSpotDetails Method contains this code:
- (void)showSpotDetails:(id)sender
{
// determine which button (spot) was selected, then use its tag parameter to determine the spot.
UIButton *selectedButton = (UIButton *)sender;
Spot *spot = (Spot *)[spotsArray_ objectAtIndex:selectedButton.tag];
SpotDetails *spotDetails = [[SpotDetails alloc] init];
[spotDetails setSpotDetailsObject:spot];
[self.navigationController pushViewController:spotDetails animated:YES];
}
The details VC does receive the object data.
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"spotDetailsObject %#", spotDetailsObject_.name);
}
The NSLog method below does output the passed object. Also, everything in the details view controller is as it was. Nothing has changed on the details VC. It just does not render anything ever since I removed the segue and added the pushViewController method. Perhaps I am missing something on the pushViewController method? I never really do things this way, I try to always use segues...
Any suggestions?
Welcome to the real world. Previously, the storyboard was a crutch; you were hiding from yourself the true facts about how view controllers work. Now you are trying to throw away that crutch. Good! But now you must learn to walk. :) The key here is this line:
SpotDetails *spotDetails = [[SpotDetails alloc] init];
SpotDetails is a UIViewController subclass. You are not doing anything here that would cause this UIViewController to have a view. Thus you are ending up a with blank generic view! If you want a UIViewController to have a view, you need to give it a view somehow. For example, you could draw the view in a nib called SpotDetails.xib where the File's Owner is an SpotDetails instance. Or you could construct the view's contents in code in your override of viewDidLoad. The details are in the UIViewController documentation, or, even better, read my book which tells you all about how a view controller gets its view:
http://www.apeth.com/iOSBook/ch19.html
The reason this problem didn't arise before is that you drew the view in the same nib as the view controller (i.e. the storyboard file). But when you alloc-init a SpotDetails, that is not the same instance as the one in the storyboard file, so you don't get that view. Thus, one solution could be to load the storyboard and fetch that SpotDetails instance, the one in the storyboard (by calling instantiateViewControllerWithIdentifier:). I explain how to do that here:
http://www.apeth.com/iOSBook/ch19.html#SECsivc

Loading a Custom ViewController with data

I have a UITableView which loads through it's navigationController a new viewcontroller.
This code goes in the tableView:didSelectRowAtIndexPath method:
ConcertDetailViewController *detailVC = [[ConcertDetailViewController alloc] initWithNibName:#"ConcertDetailViewController" bundle:nil];
The UITableView has a model, I want to sent an element of this model to the newly created ViewController.
detailVC.aProd = [_prod objectAtIndex:indexPath.row];
When the value is set I want the detailVC to draw the data on the screen. I thought a custom setter, overwriting the one generated by #synthesize would work.
-(void)setaProd:(NSMutableDictionary *)aProd {
_aProd = aProd;
[self displayAProd];
}
displayAProd just takes the values in aProd and put's them on the screen, or rather I'm setting some value of an outlet , created in my nib file.
self.prodNameLbl.text = [_aProd objectForKey:#"name"];
Nothing special about this. But it just doesn't work. I figured out why, I think.
It's because the setter executes way faster then, loading the whole view into memory.
If I put self.prodNameLbl.text = #"something"; in the viewDidLoad method it does display the correct value in the label.
A quick workaround would be the see if _concerts has been set and from there call displayAProd. Here I'm doubting myself if it's a good way to load a view. What if the custom setter takes longer to execute the loading the view. The test to see if _concerts has been set will be false and nothing will be displayed. Or is that just impossible to happen ?
Or maybe there's a better pattern for loading views and passing data to them to be displayed.
Thanks in advanced, Jonas.
The problem is that when you load the view controller from the NIB, the IBOutlets will not be connected to your UILabel and other similar properties during the initWithNibName call.
You need to wait for viewDidLoad to be called on detailVC and call [self displayAProd] from there. At this point, the connections will have been made.
Do a quick test. Put a break point in your didSelectRowAtIndexPath method and, after initialising detailVC, check to see if prodNameLbl is null or not.

Pass data to UITextField between ViewControllers

I am stuck on passing data from one ViewController to another. The scenario is as:
I have 2 ViewControllers named : SearchDomainController and LoginViewController. What i am trying to do is pass the string value from SearchDomainController to the UITExtfield in LoginViewController.
In LoginViewController i have declared IBOutlet UITextField *domainField; and also a property #property(nonatomic,retain) UITextField *domainField.
The problem is when i create a new instance of LoginViewController in SearchDomainController and try _loginViewController.domainField.text = #"Some text";
the text never changes in UItextField on LoginViewController.
What did i miss ? And what are the best solution for this kind of problem? Thanx
My guess would be that _loginViewController.domainField is nil at that time, which is probably because the view hasn't loaded yet, and the label is created when the view loads (via a nib) and not as soon as the view controller object is created.
In order to not depend on having the view fully loaded when passing the value, I would have used a separate property for passing along the title, i.e. _loginViewController.domainFieldText = #"Some text";. Then in viewDidLoad of the _loginViewController, assign the value of domaonFieldText to the actual label.
Alternatively, make sure the UILabel instance is created and not nil when you set its text from the other view controller.
Set the string as a property of the AppDelegate in one view controller, and you can retrieve it from another, and set it as textField.text

Set value of property in main view controller from dynamically instantiated class (objective-c)

I am totally out of ideas on this... I've tried so many variations that I am dizzy...
I have a main UIViewController which, at the touch of a button, adds another UIViewController to one of its subviews. When the dynamic UIVC gets added, a property in the main UIVC is updated to hold a reference to it (called currentObject). This is working fine.
The problem I am having is that if I add another dynamic UIVC, the property holding the reference is initially updated correctly, but no matter what I try, I can't get the property to update when I touch the first dynamic UIVC. Everything I try to set "currentObject" from a dynamic UIVC gives me an "unrecognized selector sent to class" error and then bails.
I'm holding off from putting code into this post at first. Not sure what I would post that would be helpful.
Thanks in advance!
Updated:
in DynamicModuleViewController.h:
#interface DynamicModuleViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIPopoverControllerDelegate, UIGestureRecognizerDelegate, UITextViewDelegate, UIApplicationDelegate, MFMailComposeViewControllerDelegate>{
DynamicModule *currentObject;
}
#property(nonatomic, retain) DynamicModule *currentObject;
in DynamicModuleViewController.m:
#implementation DynamicModuleViewController
#synthesize currentObject;
-(void)addObject:(id)sender
{
DynamicModule *dm = [[DynamicModule alloc]init];
// positioning and PanGesture recognition code to allow dragging of module
currentObject = dm;
[mainView addSubview:currentObject.view];
}
#end
when added this way, from a button tap, it works fine.
Once more DynamicModules are instantiated, I need to update currentObject with the DynamicModule that was tapped last.
adds another UIViewController to one of its subviews
First of all this is a red flag to me. Adding a UIViewController's view as a subview is almost always the wrong way to manage a view hierarchy and a common mistake in iOS apps. Please see http://blog.carbonfive.com/2011/03/09/abusing-uiviewcontrollers/ so I can stay on topic and avoid repeating myself.
currentObject = dm;
This sets the ivar backing your currentObject property directly. You are leaking the previous value of currentObject. You don't appear to be removing the previous currentObject's view from mainView. I suspect you are setting the currentObject to an autoreleased object, failing to retain it because you bypassed your setter, and eventually try to send a message to the released object resulting in either an "unrecognized selector" error as your message reaches whatever other object now occupies that memory address or a BAD_ACCESS error as you try to reference an object which no longer exists.
self.currentObject = foo is equivalent to [self setCurrentObject:foo] and is probably what you intended.
What about using the delegate pattern?