IBAction connected with button but need a void - objective-c

I have i IBAction and it's connected with a button in .xib. But for a action o needed this code;
- (void) reportScore: (int64_t) score forCategory: (NSString*) category
{
GKScore *scoreReporter = [[GKScore alloc] initWithCategory:category];
scoreReporter.value = counter;
[scoreReporter reportScoreWithCompletionHandler: ^(NSError *error)
{
[self callDelegateOnMainThread: #selector(scoreReported:) withArg: NULL error: error];
NSLog(#"Nice: %d", counter);
}];
}
Is there a way to connect my button with the void? Or something like that?
- (IBAction) subScore {
//data
}

IBAction(and IBOutlet) is just used to let XCode's Interface Builder(IB) know that there's a function exist. If you want use void, okay, but you'll not get the function shown in Interface Builder.
IBAction is a special keyword that is used only to tell Xcode(Interface Builder) to treat a method as an action for target-action connections. IBAction is defined to void.
IBOutlet is a special keyword that is used only to tell Xcode(Interface Builder) to treat the object as an outlet. It’s actually defined as nothing so it has no effect at compile time.
You can set the function(which is defined with void, and note IBAction is okay either, but needless here) to your button target like this:
[yourButton addTarget:self action:#selector(yourButtonFunction:) forControlEvents:UIControlEventTouchUpInside];
Generally, if you create your code programmatically(without using XCode's Interface Builder), you do not need IBOutlet or IBAction anymore. ;)

Related

textShouldEndEditing in NSOutlineTableView is getting called twice

I just implemented following method that suppose to take some action after the value of a NSTextField is changed in my NSOutlineView
-(BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor
{
NSLog(#"end editing");
NSTextField* tf = (NSTextField*)control;
if(selectedItem && [selectedItem isKindOfClass:[HSCategoryClass class]])
{
HSCategoryClass* c = selectedItem;
c.name = tf.stringValue;
// request the update from DB
[[NSNotificationCenter defaultCenter] postNotificationName:#"updatingCategoryName"
object:c
userInfo:#{#"sender":self}];
}
return YES;
}
However, when I'm done editing and hit enter key or navigate anywhere outside of the text field this method is getting called twice instead of just once.
Does anyone know why is this?!
Any kind of help is highly appreciated!
That routine does not signify that editing has ended. Instead, it's called to find out if it should end (hence the name of the method). It can be called by the framework any number of times, and you shouldn't be relying on it for this purpose.
Instead override the NSOutlineView's textDidEndEditing: method.
Be sure to call super.
So you'd subclass the NSOutlineView and in your subclass:
- (void)textDidEndEditing:(NSNotification *)aNotification
{
// do your stuff
[super textDidEndEditing:aNotification];
}

Presenting modal dialogs from XIB in Cocoa: best/shortest pattern?

Below is my typical WindowController module for presenting a modal dialog (could be settings, asking username/password, etc) loaded from a XIB. It seems a bit too complex for something like this. Any ideas how this can be done better/with less code?
Never mind that it's asking for a password, it could be anything. What frustrates me most is that I repeat the same pattern in each and every of my XIB-based modal window modules. Which of course means I could define a custom window controller class, but before doing that I need to make sure this is really the best way of doing things.
#import "MyPasswordWindowController.h"
static MyPasswordWindowController* windowController;
#interface MyPasswordWindowController ()
#property (weak) IBOutlet NSSecureTextField *passwordField;
#end
#implementation MyPasswordWindowController
{
NSInteger _dialogCode;
}
- (id)init
{
return [super initWithWindowNibName:#"MyPassword"];
}
- (void)awakeFromNib
{
[super awakeFromNib];
[self.window center];
}
- (void)windowWillClose:(NSNotification*)notification
{
[NSApp stopModalWithCode:_dialogCode];
_dialogCode = 0;
}
- (IBAction)okButtonAction:(NSButton *)sender
{
_dialogCode = 1;
[self.window close];
}
- (IBAction)cancelButtonAction:(NSButton *)sender
{
[self.window close];
}
+ (NSString*)run
{
if (!windowController)
windowController = [MyPasswordWindowController new];
[windowController loadWindow];
windowController.passwordField.stringValue = #"";
if ([NSApp runModalForWindow:windowController.window])
return windowController.passwordField.stringValue;
return nil;
}
The application calls [MyPasswordWindowController run], so from the point of view of the user of this module it looks simple, but not so much when you look inside.
Set tags on your buttons to distinguish them. Have them both target the same action method:
- (IBAction) buttonAction:(NSButton*)sender
{
[NSApp stopModalWithCode:[sender tag]];
[self.window close];
}
Get rid of your _dialogCode instance variable and -windowWillClose: method.
-[NSApplication runModalForWindow:] will already center the window, so you can get rid of your -awakeFromNib method.
Get rid of the invocation of -[NSWindowController loadWindow]. That's an override point. You're not supposed to call it. The documentation is clear on that point. It will be called automatically when you request the window controller's -window.
Get rid of the static instance of MyPasswordWindowController. Just allocate a new one each time. There's no point in keeping the old one around and it can be troublesome to reuse windows.

Can't close a window- why?

I have an application in which a window should be opened and closed when a checkbox is clicked on or off in a separate window. I can open it, but can't close it. I define a NSWindow in the windowControllerObject and try to close the NSWindow. The relevant code is:
buttonController.h
#interface buttonController : NSWindowController
{
NSButton *showAnswerBox;
infoWindowController *answerWindowController;
}
- (IBAction)showAnswer:(id)sender;
#end
buttonController.m
- (IBAction) showAnswer:(id) sender
{
if ([sender state] == NSOnState) {
if (!answerWindowController) {
answerWindowController = [[infoWindowController alloc] init];
}
[answerWindowController showWindow:self];
}
else {
[answerWindowController hideWindow];
}
}
infoWindowController.h:
#interface infoWindowController : NSWindowController {
IBOutlet NSWindow * infoWindow;
}
- (id) init;
- (NSWindow *) window;
- (void) hideWindow;
- (void) tsSetTitle: (NSString *) displayName;
#end
And in infoWindowController.m:
- (NSWindow *) window
{
return infoWindow;
}
- (void) hideWindow
{
[[self window] close];
}
The window opens, but it won't close. I've tried several variations, including orderOut on the infoWindowController. I'm sure I'm missing something dumb- what is it?
In IB, the only way I can even get the windows to open is if 'Open at launch' checked- shouldn't I be able to open them programmatically without that?
NSWindowController already defines a window property. You have effectively overridden the getter of that property by implementing your own -window method. The setter, though, is still the inherited version.
So, assuming you have connected the window outlet of the controller to the window in the NIB, the inherited setter is being called. That allows the inherited implementation of -showWindow: to work to show the window. But your -window method will return nil because the inherited setter does not set your infoWindow instance variable.
Get rid of your separate infoWindow property and getter. Just use the inherited window property and its accessors.
If you use NSWindowController it's better to use it's close method:
- (void) hideWindow
{
[self close];
}
or just:
[answerWindowController close];
But your code is also valid, just make sure that your [answerWindowController window] is not nil. If you load your window from xib you should initialize your window controller with the name of this xib: answerWindowController = [[AnswerWindowControllerClass alloc] initWithWindowNibName:#"YOUR WINDOW XIB NAME"];.
Also check that "Visible at launch" is unchecked for your window (it seems that it doesn't).

UITextField editingChange Control Event not works

I have some textfields and I want to do when I change textfield1 text set text to other textfields. My code below. But it not works. How can I solve this?
- (IBAction)TCKimlikTextChange:(id)sender {
[TCKimlikText addTarget:self action:#selector(yourMethod: ) forControlEvents:UIControlEventEditingChanged];
}
-(void)yourMethod: (UITextField*)tf_{
if (tf_) {
if (TCKimlikText.text == #"1") {
AdinizText.text = #"Hacer";
}
}
}
Your code is very abstract. yourMethod, tf_ TCKimlikTextChange are all expressions that are not very human readable. You should work on your variable names.
I suppose your first method is a button handler. It just assigned a target and action to the text field, but does not call any method. You do not need that action if you use the delegate protocol.
To solve your problem: implement the UITextField delegate methods. Make sure you set the delegate (probably self) for your text fields. Your view controller must mention the <UITextFieldDelegate> protocol in its .h file. Thus, in textField:shouldChangeCharactersInRange:replacementString::
if ([textField.text isEqualToString:#"1"]) {
displayLabel.text = #"Hacer";
}
Notice that you need isEqualToString: to compare strings, a simple == won't do.
If u are want to change on the click of the return button use the delegate
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if(textField == field1)
[field2 setText:field1.text];
[field1 resignFirstResponder];
return YES;
}
or u can use other delegates too like:
– textFieldShouldBeginEditing:
– textFieldDidBeginEditing:

Working backwards from null

I know that once you get better at coding you know what variables are and null popping out here and there may not occur. On the way to that state of mind are there any methods to corner your variable that's claiming to be null and verify that it is indeed null, or you just using the wrong code?
Example:
-(IBAction) startMotion: (id)sender {
NSLog(#"Forward or back button is being pressed.");
UIButton * buttonName = (UIButton *) sender;
NSLog(#"Button Name: %#", buttonName.currentTitle);
}
Button Name: (null) is what shows up in the console
Thanks
According to Apple's docs, the value for currentTitle may be nil. It may just not be set.
You can always do if (myObject == nil) to check, or in this case:
-(IBAction) startMotion: (id)sender {
NSLog(#"Forward or back button is being pressed.");
UIButton * buttonName = (UIButton *) sender;
if (buttonName != nil) {
NSString *title = buttonName.currentTitle;
NSLog(#"Button Name: %#", title);
}
}
Another way to check if the back or forward button is pressed, is check the id itself.
//in the interface, and connect it up in IB
//IBOutlet UIButton *fwdButton;
//IBOutlet UIButton *bckButton;
-(IBAction) startMotion: (id)sender {
NSLog(#"Forward or back button is being pressed.");
UIButton * buttonName = (UIButton *) sender;
if (buttonName == fwdButton) {
NSLog(#"FWD Button");
}
if (buttonName == bckButton) {
NSLog(#"BCK Button");
}
}
also, make sure your outlets and actions are all connected in IB, and that you save and re-build the project. I've gone where I changed somehting in IB, saved the .m file (not the nib) and was like "why isn't this working???"
I was using the wrong field in Interface Builder I was using Name from the Interface Builder Identity instead of Title from the button settings.
buttonName cannot be null, otherwise buttonName.currentTitle would produce an error.
Therefore the currentTitle attribute itself must be null.
Or, maybe currentTitle is a string with the value (null).
In general, in Objective-C, if you have [[[myObject aMethod] anotherMethod] xyz] and the result is null it's difficult to know which method returned null. But with the dot syntax . that's not the case.