I'm trying to connect the text fields in a sign up form so that, upon done being pressed for each, the next field in the form automatically becomes active. To achieve this, I've extended the UITextField class, as follows, in the view controller for the sign up view.
#interface UITextField (Extended)
#property (nonatomic, weak) IBOutlet UITextField* nextField;
#end
I've then set the nextField outlets via interface builder for each field in the form, and have the following code implemented in the view controller, which is also acting as the delegate for the text fields in the form.
- (BOOL) textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
UITextField* field = textField.nextField;
if (field)
[field becomeFirstResponder];
return NO;
}
However when building and running the app, it immediately crashes giving the following error :
*** Terminating app due to uncaught exception 'NSUnknownKeyException',
reason:'[<UITextField 0x78729580> setValue:forUndefinedKey:]:
this class is not key value coding-compliant for the key nextField.'
A bit lost as to how to address this, any help would be appreciated! Thanks in advance.
Just remove all the outlets and recreate them again. You just missed or duplicated one of them, since you have several textfields it is highly possible something has gone awry. And make sure that each nextField really points to next field :)
UPDATE: It's late night so I missed one big problem.
You can't add new properties via category to an existing class like that. The reason is category is not capable of creating a backing variable behind the scenes. (There is a way with associated objects..but it's best not to delve into that black magic.)
Instead of UItextField+extended category, subclass the UITextfield class.
#interface CustomTextField : UITextField
#property (nonatomic, strong) IBOutlet UITextField *nextField;
#end
Then in interface builder, you will have to set that CustomTextfield class in the class inspector for each text field.
The problem is that while you can declare a property in a category, the compiler will not define the property getter and setter for you. You have to define the getter and setter yourself.
You can use an “associated object” to store the property value. See this answer for example code. Since you don't want your nextField property to retain the next field, use OBJC_ASSOCIATION_ASSIGN instead of OBJC_ASSOCIATION_RETAIN_NONATOMIC when setting the associated object.
Related
I have some forms for the authentications and signup views and I want that all UITextField inside those forms have a UIButton as an accessory view, just above the keyboard. I want to have the possibility to set the title and the action for this button
Because I want all those text field have one and each will have a title and an action, and to avoid redundancy, I thought about a protocol.
I want something like extending a custom protocol, for example UITextFieldAccessoryViewDelegate and to be conform to some functions like :
-buttonAccessoryView title ... -> String
-didClickOnAccessoryViewButton.. -> ()
My mind is closed. Someone can give me some ideas to do what I want ?
You could use associated objects to solve this problem. This lets you add a property and its synthesized getter/setters.
#interface UITextField(AccessoryButton)
#property(readwrite, strong, nonatomic) UIButton *accessoryButton;
#end
#import<objc/runtime.h>
#implementation UITextField(AccessoryButton)
-(UIButton*) accessoryButton
{
objc_getAssociatedObject(self, #selector(accessoryButton));
}
-(void) setAccessoryButton:(UIButton *)accessoryButton
{
objc_setAssociatedObject(self, #selector(accessoryButton), accessoryButton, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
Include this category into your forms that need the UIButton for the text fields. Then assign action and title to a UIButton like how you normally do.
Considering everything you want to do I think you are better off using a subclass of UITextField rather than an extension.
Extensions can't add instance variables to the objects they extend, but subclasses can. As lead_the_zeppelin points out in his answer, you can use associated objects to simulate adding instance variables with an extension but it seems like you're making it needlessly complicated when a subclass gives you everything you want.
I'm currently writing an iPhone app that needs to pass data from a text field on the Flipside view to the Main view when the user clicks the Done button. This is the last component of a project that I am working on.
I've tried including my MainViewController.h file on my FlipsideViewController.m file, and this doesn't work. I'm currently writing in the - (IBAction)done:(id)sender portion, something like
MainController._aTextFieldOnTheMainView.text = _aTextFieldOnTheFlipsideView.text;
but I always get this error: Property '_aTextFieldOnTheMainView' not found on object of type 'MainViewController'.
What am I doing wrong?
Change/remove your weak declaration of #property (weak, nonatomic) IBOutlet UILabel *aTextFieldOnTheMainView;. This causes the deallocation of the property when the flipsideview comes onto the screen.
hope this helps
I'm trying to change the color of some placeholder text, of a UITextField, but i having problems reaching the text field. I've created a property with Referencing Outlets, like this:
#property (retain, nonatomic) IBOutlet UITextField *usernameField;
But can't reach it with either usernameField or _usernameField. What am i missing?
If you have a property, do NOT synthesize it. That just complicates things, and is no longer needed in Objective C 2.0.
Don't use _usernameField. That bypasses the property getter/setter and accesses the iVar directly.
Use self.usernameField instead. Until you understand the difference, use the property except in the code of a custom getter/setter or dealloc method.
first you should use self.usernameField and second just make sure you assigned the outlet to the UITextField you need to access it in the Interface Builder.
You can check it. Have you connected the outlet of the textfield in the xib file?
I'm trying to create an iPad/iPhone app that dynamically creates menus depending on a JSON object that is returned from a RESTful API. Specifically I'm trying to show/hide a UIPickerView that I created using the interface builder. In the properties menu in the interface builder I checked the box "hidden" for that UIPickerView. I used this tutorial to create to UIPickerView. I've set the delegate and data source to the View Controller using the interface builder. I'd like to unhide/show the UIPickerView when a certain condition is met. So far I've tried the following code:
[self.choicePicker setHidden:NO];
self.choicePicker.hidden = NO;
I usually build such object programmatically but I thought I'd try it this way. I've looking through various stackoverflow posts and doing research but I can't seem to find something that works. I'm new to programming in Objective C. Thanks in advance any help is greatly appreciated.
.h file code
#interface slrpViewController : UIViewController<UITextFieldDelegate, UIPickerViewDelegate, UIPickerViewDataSource>
{
IBOutlet UIPickerView *picker_choice;
NSMutableArray *dataArray;
NSMutableData *receivedData;
}
#property(nonatomic, strong) UILabel *nameLabel;
#property(nonatomic, retain) UIPickerView *choicePicker;
.m file code
-(void)buildChoicesMenu:(NSDictionary *)choiceDict{
//in this method we build the choices menu
[self.choicePicker setHidden:NO];
self.choicePicker.hidden = NO;
if (self.choicePicker) self.choicePicker.hidden = !self.choicePicker.hidden;
}
You have two different picker views defined. One a property choicePicker (and an implicit _choicePicker instance variable), and another instance variable picker_choice. It seems you have connected your picker_choice in interface builder, but are trying to modify the property. In fact, if you try to print po self.choicePicker in the debugger, you would get nil, because there is nothing filling it.
Either remove the instance variable, and connect your property in interface builder, or synthesize your property with your instance variable by doing so:
#syntesize choicePicker=picker_choice
When I created a UISwitch element in my storyboard, and attached it to the .h file, there was this line generated in the controller:
#property (weak, nonatomic) IBOutlet UISwitch *wantHelp;
And I was trying to figure out how to make the system notice when the value was changed, so I tried to manually add something like this below the original statement:
- (IBAction)wantHelp:(id)helpToggle;
and in the controller, I have something like this:
-(IBAction)helpToggle:(id)sender
{
NSLog(#"sender is: %#", sender);
if (wantHelp.on)
{
NSLog(#"yes");
}
else
{
NSLog(#"No");
}
}
What I wanted to do is connect the helpToggle IBAction with the particular UISwitch element, but when I run it, I get an error: unrecognized selector sent to instance which as I understand is means that I called an operation on an incorrect object.
Could someone help me understand what I am doing wrong here?
Thanks!!
This is how my .m file looks like:
#interface PlanBusinessController ()
#end
#implementation PlanBusinessController
#synthesize businessDescription;
#synthesize personName;
#synthesize personEmail;
#synthesize privacy;
#synthesize wantHelp;
-(IBAction)helpToggle:(id)sender
{
NSLog(#"sender is: %#", sender);
if (wantHelp.on)
{
NSLog(#"yes");
}
else
{
NSLog(#"No");
}
}
What's happening is that your UISwitch has been told to call wantHelp: however as no method called this exists in you implementation file (.m file) that is why the 'unrecognized selector sent to instance' error is being called.
So you can have as many IBAction as you want or one it doesnt matter. What matters most is declaring it in your .h file, going into interface builder and linking the desired action to that IBAction.
so you have your IBAction
-(IBAction)WHATEVERNAME:(id)sender
then go to interface builder and click on your File's Owner object(kinda top left). then click on the Connections Inspector (top right)
and drag from the dot where it says WHATEVERNAME to your object (UISwitch wantHelp)
when you do that it will ask you what action you want to receive
take in mind the reason for (id)sender is that you are suppose to cast your object
UISwitch * tempSwitch = (UISwitch*) sender;
so that you have a pointer to the switch object
this is because you could have this same IBAction method handle many different types of objects
although this is all good stuff the actual error came from multiple selectors being called. Once we got into the connection inspector we were able to see the 2 different methods being called by it. One was the valid IBAction and the other was a previously declared method wantHelp
Okay so all the answers failed to give you "the easy way"
Hold down control on your UISwitch and drag it to your .h file.
You will then see a dialog box which will allow you to select the "Connection"
This connection determines if you are creating and IBOutlet or an IBAction.
Once you change it to "Action" you will then have it automatically select "ValueChanged" as the event, and you can give it whatever name you want:
I named it helpSwitchToggled. Then you will have your IBAction in the .h, and in the .m files.
In your .m file you can then write your code for the value changed action:
for copy paste:
- (IBAction)helpSwitchToggled:(id)sender {
if(self.helpSwitch.on)
{
//Do the On stuff
} else {
//Do the Off Stuff
}
}
That is "The easy way" to make an action associated with something on your interface.
The difference between IBAction and IBOutlet has been pointed out in other answers, but basically Actions are responses to control events and Outlets are connections to elements within the view.
IBAction is merely a tag to let Interface Builder know it can attach to that action.
IBAction is defined as void but with the name Interface Builder allows you to drag your connection over it and connect an event from an object to that function.
Other than that Your actions should have meaningful names. helpToggle seems to me to be an on off switch. but usually I would include a bit of description in that message as well. Such as
- (IBAction) helpSwitchToggled:(id) sender{
}
this message gives you a very meaningful name and reading it will tell you exactally what is calling it as well as the type of message that object is sending.
In conjunction I would also have an IBOutlet for that switch called helpSwitch, Like this one.
#property (nonatomic, weak) IBOutlet UISwitch *helpSwitch;
as you can see. that object is clearly a switch. And IBOutlet is actually defined as nothing. but it again is a tag that Interface Builder uses to know you have a property that can be linked to with Interface Builder.
IBAction and IBOutlet are nothing more than Metadata that tells the Interface builder that this is a possible connection. Connecting them is up to you and the compiler treats them like nothing.
I hope this information helped you :)