Why can I not reset a text field within an IBAction associated with it? - objective-c

I have an IBAction called keyboardResponse associated with a text field called myTextFieldIBOutlet via the "Editting Changed" event handler in the xib:
- (IBAction)keyboardResponse:(id)sender
{
// process this single character - function I wrote else where that works fine.
[self processSingleCharacter:myTextFieldIBOutlet.text];
// clear input text
myTextFieldIBOutlet.text = #"";
}
It's supposed to clear the input after the user types something into it.
I get a run time error with this code in iOS Simulator:
Thread 1: EXC_BAD_ACCESS (code=2, address=0xbf7fff0c)
Why? I had synthesized the IBOutlet myTextFieldIBOutlet already.

if myTextFieldIBOutlet is synthesized, you should change the last line to:
self.myTextFieldIBOutlet.text = #"";
If the textfield you want to clear is the same control that calls this action, you can also use the sender variable you are sending
[sender setText:#""];

Related

Obj-C IBAction (id)sender

I have an IBAction like:
- (IBAction)thisThing:(id)sender {
[self doSomething];
}
I would like do this (manually call the IBAction):
[self thisThing];
However I obviously need to do [self thisThing:...];. <- (what the heck goes after the colon?)
I'm not sure what (id)sender is supposed to be. How do call it manually without needing to click the button that it's tied to? I searched for anything about IBAction (id)sender and the results came up completely empty.
what the heck goes after the colon?
Well it depends on how you have written code inside the IBAction. Say for a calculator app, if all buttons are hooked up with the same IBAction then you would need sender (in this case NSButton) to identify which button got touched/clicked.
-(IBAction) buttonClicked:(id) sender {
// sender's identifier or Tag will let us know the number clicked here
[self doSomeThing];
}
But if you had IBActions for each and every button you would not need to be dependent on sender.
-(IBAction) firstButtonClicked:(id)sender;
-(IBAction) secondButtonClicked:(id)sender;
and so on ...
So in the first case if I want to programatically invoke the action I would pass the sender with appropriate attributes set to make sure the correct button got clicked. In second case just pass nil as it does not depend upon sender's value.
While popeye's comment answers your question, here's another perspective.
You have complete control over the action method. If you aren't using the sender parameter for anything in that method, then you do not have to supply it when calling it manually. By not supply it I mean pass nil as the value of the parameter.
Normally, it will contain a pointer to the control that is wired up to the action. If you did want to use if for something, they you would simply cast sender to the type of the control and do whatever with it.
- (IBAction)thisThing:(id)sender
In here,
- denotes the start of a instance method, whereas + means class(static) method.
( .. ) indicate return type. IBAction is actually void. Using IBAction instead of void tells that this method will be associated with UI(.nib) events.
thisThing is the name of the method, followed by parameter list.
In C view point, actual function names is something like thisThing:. That is, number of parameter modifies function name (external linkage).
If you meant to call thisThing: but write [self thisThing], you are calling different (not existing) method.
So, you must write :. What actual value to pass? One can decide this by looking at the method implementation.
If you have the IBOutlet of the button, you can pass that like [self thisThing:btn];
Or simply pass nil, [self thisThing:nil]; (if you are not using sender inside the IBAction)
- (IBAction)thisThing:(id)sender {
}
Is an event handler. That means that it is called when an event is sent by someone. A typical example of an event is a click on a button, it that case, the button sends the event (that means the button, a NSButton instance, is the sender).
Having the sender as a parameter is useful when you use the same event handler for events coming from different sources, e.g.
- (IBAction)buttonTapped:(id)sender {
if (sender == self.myButton1) {
//button 1 was tapped
}
else if (sender == self.myButton2) {
//button 2 was tapped
}
}
If this case, if you want to call the event handler manually, you just call
[self buttonTapped:self.myButton1];
If you don't use the sender parameter, then you can simply call
[self buttonTapped:nil];
However, the parameter is completely optional, so you can eliminate it:
- (IBAction)buttonTapped {
// ...
}
[self buttonTapped];
On a separate note, it's never good to call event handlers manually. Event handlers serve to handle events. If you need to perform the same action manually, separate it from the event handler, e.g.
- (IBAction)buttonTapped {
[self doSomething];
}
instead of calling [self buttonTapped], call [self doSomething]

How does (id)sender work in cocos2d?

The following code works good for me:
In the init method of a menu layer:
CCMenuItemFont *item1 = [CCMenuItemFont itemWithString:#"Level 1" target: self selector: #selector(startLevel:)];
item1.userData = (__bridge void*) ([NSNumber numberWithInt:1]);
...//create menu and add in the item1
-(void)startLevel: (CCMenuItem *)sender
{
NSNumber *number = sender.userData;
...
}
My questions are:
I didn't pass item1 when call the method startLevel: how does it know that the sender is item1?
is it written into selector? or is it written in cocoa?
CCMenuItem passes itself as parameter to this selector. Details are in CCMenuItem source code.
Regarding omitting passing itself as a parameter, do you mean like...
- (void) pushedStart : (id) sender
{
//start game
}
but you can't do
[self pushedStart];
because it needs a parameter? If so, what you can do this:
id junkID;
[self pushedStart: junkID];
JunkID will initialize to whatever the hell it is an unassigned ID assigns to, so you pass it as a reference and just don't use it for anything, which is good if you want to have a "start game" button but have the game automatically start inside of a timer or whatever else you're doing with your buttons
As a side note, and getting more into the guts of cocoa, the way it KNOWS (and what YOU must not forget) is that colon. When you call a function you put the variable after a colon [self eat: food];
When you put together the menu item you set it up with target:self, which makes the button use itself (not the layer "self" you use when you call [self eatABanana]) as a target. The button push of
menuButton = target:self selector:#selector(pushButton:)
is represented like
[self pushButton:menuButton]
If you forgot that colon, it's the same as calling a function and not passing the variable, which doesn't give a very helpful error message insofar as it doesn't help you locate where the problem is occurring. I've spent hours upon hours chasing down memory crashes resulting from writing #selector(startGame) instead of #selector(startGame:) in those damn menu buttons. I always feel stupid when I finally figure it out.

Update property bound from text field without needing to press Enter

I have a text field and I bind it to an NSString instance variable.
When I type in the text field, it does not update the variable. It waits until I press the Enter key. I don't want to hit Enter every time.
What do I need to change in order to make the binding change value immediately?
By default, the value binding of an NSTextField does not update continuously. To fix this, you need, after selecting your text field, to check the "Continuously Updates Value" box in the Bindings Inspector under the Value heading:
However, most often, what you really want to do is update the property to which the text field is bound when the user has finished editing and presses a button ("Save" or "OK", for example). To do this, you needn't continuously update the property as described above, you just need to end editing. Daniel Jalkut provides an extremely useful implementation of just such a method:
#interface NSWindow (Editing)
- (void)endEditing;
#end
#implementation NSWindow (Editing)
- (void)endEditing
{
// Save the current first responder, respecting the fact
// that it might conceptually be the delegate of the
// field editor that is "first responder."
id oldFirstResponder = [oMainDocumentWindow firstResponder];
if ((oldFirstResponder != nil) &&
[oldFirstResponder isKindOfClass:[NSTextView class]] &&
[(NSTextView*)oldFirstResponder isFieldEditor])
{
// A field editor's delegate is the view we're editing
oldFirstResponder = [oldFirstResponder delegate];
if ([oldFirstResponder isKindOfClass:[NSResponder class]] == NO)
{
// Eh ... we'd better back off if
// this thing isn't a responder at all
oldFirstResponder = nil;
}
}
// Gracefully end all editing in our window (from Erik Buck).
// This will cause the user's changes to be committed.
if([oMainDocumentWindow makeFirstResponder:oMainDocumentWindow])
{
// All editing is now ended and delegate messages sent etc.
}
else
{
// For some reason the text object being edited will
// not resign first responder status so force an
/// end to editing anyway
[oMainDocumentWindow endEditingFor:nil];
}
// If we had a first responder before, restore it
if (oldFirstResponder != nil)
{
[oMainDocumentWindow makeFirstResponder:oldFirstResponder];
}
}
#end
So if for example you had a "Save" button targeting your view controller's method -save:, you would call
- (IBAction)save:(id)sender
{
[[[self view] window] endEditing];
//at this point, all properties bound to text fields have the same
//value as the contents of the text fields.
//save stuff...
}
The previous answer is beautiful, and I learned from it about tricking the Window/View/Document system to end-editing on everything at the programmer's will.
However, the default responder chain behavior (including the preservation of the first responder until the USER moved their focus to something else) is fundamental to the Mac's "look and feel" and I wouldn't mess with it lightly (I swear I did very powerful things in responder-chain manipulation, so I don't say that out of fear.)
In addition - there is even a simpler method - that does not require changing the binding. In the Interface-builder, select the text field, and select the "Attribute Inspector" tab. You'll see the following:
Checking the red-circled "continuous" will do the trick. This option is basic and older even than binding, and its main use is to allow validator object (a whole new story) to validate the text and change it on the fly, as the user types. When the text-field calls validator calls, it also updates bound values.

Trouble while adding column - Cocoa

just a simple problem (I hope !)
I've got a void method which add a column to a table.
Why if I call that method programmatically (ex: [self method] ) my table won't update and instead if i call it through an IBAction (pushing a button from app) it works ?
Actually i can see from the log that the method is called in both cases but update data just with IBAction.
the method:
- (IBAction)void {
NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:#"1"];
[column setWidth:50];
[tableData addTableColumn:column];
[tableData reloadData];
[[column headerCell] setStringValue:#"aColumn"];
NSLog(#"Method called"); //The method is called in both cases
}
I can't find out what I am doing wrong.
(New to cocoa programming)
Thanks a lot !
Where did you call this programmatically? You might have called it before the view was loaded in an init method instead of something else like awakeFromNib.
I tried your code and got different results. It was called fine from code (and the table updated), but not from the button (and the log wasn't run either when attempting to call from the button).
The problem is the method name -- you shouldn't name a method void. Do you not get the error message in the console: "Could not connect the action void: to target of class AppDelegate"
The compiler won't even allow me to connect that method to the button (it looks like I can in IB, but I get that error message, and if I put the method in the .h file, it has no circle next to it that shows whether it's connected or not).

Change label text based on textfield

I'm making a little demo app and I'm having trouble changing.
Heres the thing:
I have a UIButton that every click will add a character in a NSString in a UITextField.
And I put an IBAction(Mudar_Resposta) on that UITextField(campo) in the part 'Value Changed'.
In that IBAction, I put that:
- (IBAction)MudarResposta:(id)sender {
campo.text=#"lol";
}
But I can't get it to work. Any ideas?
Thanks.
The proper way to get it to work is to connect an action method to the Touch Up Inside event for your button. Within that method, edit they text for your text field.
- (IBAction)mudarResponsta:(id)sender { // Connect to Touch Up Inside of your button
campo.text = [NSString stringWithFormat:%# %#", campo.text, #"lol"]; // Add string ' lol' every time it's called
}
Connecting to Value Changed will never invoke the method because the value is never being changed—you're connecting the changing method to the change…if that makes any sense.
Most likely you didn't connect that action to anything in the XIB file.
- (IBAction)Button:(id)sender {
[self.contacts addObject:_txtField.text];
_txtField.text=#"";
}
Here contacts is an Array name which is a Mutable Array. txtField is UITextField.