need Clarification on NSButton Creation and Usage - objective-c

I have below code to create simple NSButton in a separate function
-(void)myFunction
{
NSButton *btn = [self createButton:#"Button_Name"];
if(some condition )
{
[btn setEditable:YES];
}
}
- (NSButton*)createButton:(NSString *)buttonName
{
NSButton *btn = [[NSButton alloc] initWithFrame:NSMakeRect(20, 0, 20, 20)];
[btn setButtonType:NSSwitchButton];
[btn setImagePosition:NSImageOnly];
[btn setTarget:self];
[btn setTitle: buttonName];
return btn;
}
In my same It is working fine.I am using this code in a Big project.Will It work normally or will cause some problem.Is this a correct way?

Few things I would like to bring in your notice:
You pass buttonName and buttonTitle but never uses it.
You create an object of type NSButton but your object name is against the convention, by reading btnCell someone will expect it to be NSButtonCell.
In the above code I cant see any reference to the newly created button and even you are not adding it to any view. (I hope in your real Big project you are not missing those.)

Related

How to create a action to a button in Cocoa programmatically?

I'm trying to create a button in Cocoa in mac programmatically, but I don't know how to put a action on this, I'm trying like this:
NSRect frame = NSMakeRect(10, 200, 80, 100);
NSButton *btn = [[NSButton alloc]initWithFrame:frame];
[btn setButtonType:NSMomentaryPushInButton];
[btn setBezelStyle:NSRoundedBezelStyle];
[btn setTitle:#"Click me"];
[btn setAction:#selector(hideLabels:)];
[view addSubview:btn];
but the line [btn setAction:#selector(hideLabels:)]; don't work, how can I create a action here?
the method hideLabels is in function, because I used it with another button.
Does your hideLabels method take an argument?
if not, leave off the : from the selector

UIButton addTarget: self ... causes "Does not recognize selector" error

I initialised my UIButton-deriver liek this:
Button * it = [[Button alloc] initWithFrame:CGRectMake(x, y, image.size.width, image.size.height)];
Then, I do the next:
[(UIButton *)self addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[view addSubview:self];
The first line causes "Does not recognize selector" error.
Selector buttonClicked: looks like this:
-(IBAction) buttonClicked:(id)sender {
if (action) action();
else NSLog(#"Clicked.\n");
}
What am I doing wrong?
Add the action with:
[it addTarget:self
action:#selector(buttonClicked:)
forControlEvents:UIControlEventTouchUpInside];
and then add the button with
[view addSubview:it];
And don't create UIButtons with init... use the class method + buttonWithType:.
Be careful to to subclass UIButton, I am not sure if you really want this. Have a look at create uibutton subclass.
You create buttons with +(id)buttonWithType:(UIButtonType)buttonType

UIButton created runtime in a loop, now I need a specific function depending on the button touched

I am creating some buttons and putting them inside a UIScrollView like this:
int i = 0;
while (i != numberOfButtons ) {
int updatetY = 160*i;
CGRect buttonFrame = CGRectMake(updatetY, 0, 160, 60);
UIButton *button = [[UIButton alloc] initWithFrame:buttonFrame];
UIImage *buttonImage = [UIImage imageNamed:#"bg.png"];
[button setBackgroundImage:buttonImage forState:UIControlStateNormal];
[button setTitle:[buttonsArray objectAtIndex:i] forState:UIControlStateNormal];
[button addTarget:self action:#selector(MYPROBLEM) forControlEvents:UIControlEventTouchUpInside];
[menuScrollView addSubview:button];
i++;
}
Now I need to build a method to capture which button is being touched, and run a specific bunch of code (see (MYPROBLEM).
Anybody knows what I can do to "trace" which button is being touched and then run a specific function?
something like:
-(void) buttonfunction
{
case ...
doThis
case...
doThat
}
thanks in advance.
You need to use the tag property of the uibutton control. It's a numeric id for the button. You can set a tag on the button based on the i variable in your loop, for instance:
button.tag=i;
Then in your button's action message, you would simply add the id of the button as a parameter and check its tag like so:
-(void) buttonFunction:(id)sender {
switch (sender.tag)
{
//code goes here
}
}
Hope this helps.

Adding context to a UI control or NSObject

It's great to be able to addTarget on a UIButton. I only wish there was some sneaky way I could attach state to the UIButton so that when the target method is invoked, I could magically pull that state (any id) from the sender.
Something like:
[button shoveMyObjectInThere:foo];
[button addTarget:self action:#selector(touchyTouchy:) forControlEvents:UIControlEventTouchUpInside];
Followed by:
-(void) touchyTouchy:(id) sender {
UIButton button = (UIButton*)sender;
id foo = [button getByObjectBack];
// do something interesting with foo
}
Would be great if UIButton had an 'id context' property where developers could shove stuff, but that doesn't seem to be the case. Objective-C is a very dynamic language though, so I wonder if there is some sneaky way I can add method or fields to an object at runtime?
You could try making an associative reference
#import <objc/runtime.h>
objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy);
objc_getAssociatedObject(id object, void *key);
What about something like setValue:forKey:, a part of the Key-Value coding feature of Objective-C?
So I just did a quick test and found some interesting results.
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:#"Hello" forState:UIControlStateNormal];
[button addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
button.frame = CGRectMake(100, 100, 100, 100);
[self.window addSubview:button];
// ...
- (void)buttonClicked:(id)sender {
NSLog(#"button clicked %#", [sender class]);
}
This prints: button clicked UIRoundedRectButton
So it seems like this should be possible... Truth be told, I ran into some problems subclassing UIButton to get the full example working but this seems promising. :)
The official solution is to use the "tag" property:
[self.someMutableArray addObject:foo];
button.tag = self.someMutableArray.count - 1;
[button addTarget:self action:#selector(touchyTouchy:) forControlEvents:UIControlEventTouchUpInside];
Then:
-(void) touchyTouchy:(id) sender {
UIButton button = (UIButton*)sender;
id foo = self.someMutableArray[button.tag];
// do something interesting with foo
}
In most situations you'd use an enum or constant for the tag, but an array is obviously more flexible.

Programmatically Creating Controls in Cocoa

According to Cocoa Programming for Mac OS X, 3rd Edition, on page 245 (chapter 17), you will usually create views in Interface Builder. However, it is possible to create them in code, a la:
NSView *superview = [window contentView];
NSRect frame = NSMakeRect(10, 10, 200, 100);
NSButton *button = [[NSButton alloc] initWithFrame:frame];
[button setTitle:#"Click me!"];
[superview addSubview:button];
[button release];
That’s all well and good, but how would I wire up said control’s outlets to actions in code? (In .NET, this is an easy thing; add a delegate ... I’m hoping it’s similarly easy in Cocoa/Obj-C.)
You can wire them up using a simple assignment. To continue your code from above:
[button setTarget: self];
[button setAction: #selector(myButtonWasHit:)];
And if you want to target the first responder rather than a particular object:
[button setTarget:nil];
[button setAction:#selector(myAction:)];
Swift:
button.target = self
button.action = "myAction:"
And of course add myAction function to self:
func myAction(sender: NSButton) {
println("click!")
}