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
Related
I have two view controllers, one with a text field and a 'Next' button and another one with just a label. The idea is that you fill in your name in the text field and click 'Next'. It should then switch to the other view and the label should show your name.
When I switch views however, the label is just empty. I am rather new to Objective-C and I'm hoping someone knows why this is happening :).
ViewController.m:
#interface ViewController () {
IBOutlet UILabel *label;
IBOutlet UITextField *textField;
}
-(IBAction)go:(id)sender
{
label.text = textField.text;
}
-(IBAction)remove:(id)sender {
[sender resignFirstResponder];
}
You said that you have two View Controllers. The first View Controller has an instance of UITextField, and a UIButton. Your second View Controller just has an instance of UILabel.
However, I noticed in your code that ViewController.m, which I am assuming is your first View Controller, has two IBOutlets, one for a UILabel and one for a UITextField, which doesn't make sense because the UILabel is supposed to be part of your second View Controller.
What you need to do is properly delete the IBOutlet for the UILabel from your first View Controller. Then, in your second View Controller, add the IBOutlet for it's UILabel.
Then, you need to implement the prepareForSegue method in your first View Controller and add a code statement like this:
[[segue destinationViewController]label].text = textField.text;
This way, when the segue is performed, you will successfully pass your first View Controller's text field's text to your second View Controller's label.
I am creating some sample applications to understand the concepts of view navigation, binding etc in cocoa.
Here is the scenario:
I have a window that has a tab view(2 tabs) in MainMenu.Xib.
I have a text field in the first tab and label in the second tab. I want both of them to reflect the same value and I want to do this using binding. Also, I don't want to use the views provided to me along with the tab view.
These are the steps I have done.
The view of each tab view item is set separately in the applicationDidFinishLaunching: method using the following code:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
//initialize view controllers
view1=[[ViewTab1 alloc] initWithNibName:#"ViewTab1" bundle:nil];
view2=[[ViewTab2 alloc] initWithNibName:#"ViewTab2" bundle:nil];
//set views
[[[myTabView tabViewItems] objectAtIndex:0]setView:view1.view];
[[[myTabView tabViewItems] objectAtIndex:1]setView:view2.view];
}
myTabView is the outlet reference of the tab view from MainMenu.xib in AppDelegate.
ViewTab1 is the name of the first view controller (and the xib).
ViewTab2 is the name of the second view controller (and the xib).
ViewTab1 has one single text field (and an associated label). I have bound this to a variable(name) declared in AppDelegate.
ViewTab2 has a label. I have bound this also to the same variable in AppDelegate.
The variable, 'name' is initialized in the init method of AppDelegate.
AppDelegate.h
....
NSString *name;
....
#property(strong) ViewTab1 *view1;
#property(strong) ViewTab2 *view2;
#property (assign) IBOutlet NSTabView *myTabView;
#property (strong) NSString *name;
....
AppDelegate.m
....
#synthesize myTabView;
#synthesize view1,view2;
#synthesize name;
....
- (id)init {
self = [super init];
if (self) {
name=#"dummy";
}
return self;
....
Apart from this I haven't done any coding in my program.
In the ViewTab1.xib I got an object and made it an instance of AppDelegate and then connected the delegate reference of the Application object(NSApplication) to the same object. (I hope this is the right way of getting the AppDelegate object.)
I did the same in ViewTab2.xib
Then I bound the text field in ViewTab1 and label in ViewTab2 to this variable in AppDelegate.
When I run the program both the text field and label shows "dummy". But when I change the value in the text field, its not reflected in the label in the second tab( i.e. ViewTab2).
Please tell me what I'm doing wrong.
How to establish binding to the same App delegate object from any loaded Nib?
Yes, I know this frustrated situation as described in question... after many weeks and hundreds pages of documentation for KVO - Notifications - Bindings I think there is one very simple solution for that.
As we can find in some information sources the nib-loading process produce new instances of members... and we need to use binding connection to the old one.
Note that bindings made in InterfaceBuilder are redirect to these new instances automatically after loading nib
Why not redirect the pointer of App delegate to the old instance?
In method where you loads your nib you can test which object is app delegate before and just after nib load.
If the new one isn’t the same as the previous one you can redirect it as you want.
This simple example works for me in Xcode3 under 10.5.8 with target to OSX10.5 / i386:
// ***** SOMEWHERE IN DEFAULT APP-DELEGATE.m IMPLEMENTATION
- (IBAction) createOtherWindowFromNib: (id)sender
{
// ensure that app delegate is set as you want...
[NSApp setDelegate:self];
NSLog(#"APP-DELEGAT **** CREATE-TEST-WINDOW ***** WHO IS APP-DELEGATE BEFORE NIB LOAD: %# ", [[NSApp delegate] description]);
// we can bind members of the nib to this controller over proxy object named "File’s Owner"
NSWindowController *otherWinCapo = [[NSWindowController alloc] initWithWindowNibName: #"OtherTestWindow"];
NSLog(#"APP-DELEGAT **** CREATE-TEST-WINDOW ***** WHO IS APP-DELEGATE AFTER NIB LOAD: %# ", [[NSApp delegate] description]);
// make some test for delegates before/after here if you need ...
// usually your bindings made inside "OtherTestWindow.xib" by IB doesn’t works in this moment
// ... and some redirection if needed
[NSApp setDelegate:self];
// afer that the bind made in IB inside "OtherTestWindow.xib"
// referred to (proxy object) "Application.delegate.myBOOL" (Bind to:Application, Model Key Path:delegate.myBOOL)
// react to changes of myBOOL placed in default app delegate object as expected
// simultaneously in every open instance of "OtherTestWindow.xib"
[otherWinCapo showWindow: otherWinCapo.window]; // we need populate the window instance on screen to see it
}
I think the problem is that the objects in your xibs that you set to the app delegate class create 2 different instances of the app delegate, so changing the value of the text field changes the value of name in one instance but not in the other. That's what you're doing wrong, unfortunately, I can't think of a solution at this time.
Have you turned on 'Continuously Updates Value' in the NSTextField controls?
See this example.
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.
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?
I have a view controller that is instantiated in appDelegate and pushed onto a navigation controller. The view controller's view is created with a xib file. The xib file puts a UILabel on the view (among other things). Now I need to set the label's text property programatically but I don't see how to get a reference to it. How do I reference the label object?
I'm using xcode 3.2.5 and building an iPad app.
Aside from IBOutlets, you can also set a tag property on the label in the IB. Then, when you need it you can do:
UILabel *label = (UILabel *)[self.view viewWithTag:111];
111 of course being the tag you assigned to the label in IB.
You do this with what's called an "outlet". You define them in your controller, mark them clearly as IBOutlet and then connect them in Interface Builder to your file owner (or other delegate object created in IB).
For instance, in your FooController.m you might have this:
#interface FooController ()
#property (nonatomic, weak) IBOutlet UILabel* fooLabel;
#end
Then you would select your label, and either control drag from it to the file owner, or go to its connections tab, and drag from the + under referencing outlet, to the file owner and select the fooLabel.
UPDATE: Code sample changed to reflect modern way of handling this case.
[self.view viewWithTag:NUMBER_OF_TAG]; does the trick. But remember that if you want to access the view you must do it on the viewWillAppear or viewDidAppear events.