drawRect not called for custom UIButton subclass when highlighted - ios

When using drawRect for a custom UIButton subclass, it never seems to get called to draw the button when highlighted. Do I need to call setNeedsDisplay for my button in my touch events?

I found an easy solution.
Just add the following method to your UIButton subclass:
-(void)setHighlighted:(BOOL)highlighted
{
[super setHighlighted:highlighted];
[self setNeedsDisplay];
}
That's it!

As far as i can tell there is no straight forward way to subclass UIButton.
UIButton is not the actual class type that is returned by the initializers. UIButton is kind of a front for a series of private classes.
Say you had:
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
NSLog(#"myButton type: %#", [myButton description]);
You will find the type returned in the log to be "UIRoundedRectButton". The problem with that is you would need to have extended "UIRoundedRectButton". That is not possible as it is a private class which is only ever returned to UIButton.
On top of that "UIRoundedRectButton" is not the only possible returned class all of which are private.
In other words UIButton was built in manner that is not suited to be extended.

I had the same problem and satisfying success with the following added to my UIButton subclass
- (void)awakeFromNib {
[self addTarget:self action:#selector(redraw) forControlEvents:UIControlEventAllEvents];
}
- (void)redraw {
[self setNeedsDisplay];
[self performSelector:#selector(setNeedsDisplay) withObject:self afterDelay:0.15];
}

Related

Custom UIButton class, is there a was clicked event?

I'm trying to make a custom UIButton class called BubbleButton. It will perform some animations when the button is clicked and released. Are there methods that I can put in that will be called when the button is pressed or released? Such as didClicked or something like that?
There are only (really) two that you should be worried about, setSelected and setHighlighted. setHighlighted is called immediatly after the button is pressed and setSelected is called if you hold the button for like 1/2 a second. There is also a focused state but thats not really relevant. Here is an example of a UIButton I subclasssed:
-(void)drawRect:(CGRect)rect{
[super drawRect:rect];
//Set unhighlighted state
if (self.highlighted) {
//Set highlighted state
}
}
-(void)setHighlighted:(BOOL)highlighted {
[super setHighlighted:highlighted];
[self setNeedsDisplay];
}

Alternative option of UIButton addTarget:action:forControlEvents: method in IOS

I know that this question has been asked so many times but i want to pass a custom object as an argument on clicking a button.
UIButton addTarget:action:forControlEvents: doesn't allow us to do that but it is important for me so I can do further on the basis of custom objects.
If an alternative for add target is possible, so please give the solution.
The code is like this:
Custom Object:
HeaderData *cell ;
Button:
_forward =[UIButton buttonWithType:UIButtonTypeRoundedRect];
[_forward setTitle:#"F" forState:UIControlStateNormal];
_forward.frame = CGRectMake(300, (_CELL_HEIGHT-_LABEL_HEIGHT)/2, 10 ,_LABEL_HEIGHT);]
[_forward addTarget:web action:#selector(functionName:) forControlEvents:UIControlEventTouchUpInside];
and the function which is called on clicking the UIButton _forward is:
-(void)functionName:(UIButton *)sender{
//code for further programming on the basis of cell.
}
You could make a custom subclass of UIButton:
#interface CustomDataButton : UIButton
#property (nonatomic, strong) id userData;
#end
Then in functionName, you can pull the data back out:
-(void)functionName:(UIButton *)sender
{
if ([sender isKindOfClass:[CustomDataButton class]])
{
id customData = ((CustomDataButton *) sender).userData;
}
}
caveat: written without an IDE. Watch out for typos etc.

Subclassing an UIButton: custom behaviour on "touchUpInside"

I am subclassing an UIButton which is going to be present in all of my app's ViewControllers, kinda Navigation Button. I would like just to put it to my VC and apply custom class, without any code in ViewController itself. So, the questions:
1. is it possible?
2. I am using this code now in my UIButton custom class. What is wrong?:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self addTarget:self action:#selector(didTouchButton) forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
- (void)didTouchButton {
NSLog(#"YEAH, it works, baby!");
}
UPD: seems that even initWithFrame method is not being called at all.
Loading from the nib I think.The initWithFrame method doesn't work if not called programatically.
Try -awakeFromNib Method
See this question

How to Reference UIImageView (Xcode iOS)

I've just started learning the basics of Xcode and Objective C and I am making a basic torch app as a starting point.
I've already picked up most of the basics of things, but I don't know how to make a reference to another element from an separate action (I have no idea if this terminology is correct).
For example:
- (IBAction)screenButtonClicked:(id)sender {
UIButton *button = (UIButton *)sender;
if (_ScreenOnOff) {
[self.view setBackgroundColor:[UIColor blackColor]];
[button setTitle:#"Screen (Off)" forState: UIControlStateNormal];
}
else {
[self.view setBackgroundColor:[UIColor whiteColor]];
[button setTitle:#"Screen (On)" forState: UIControlStateNormal];
}
_ScreenOnOff = !_ScreenOnOff;
}
I have a button on the storyboard which is linked to that, and I have a UIImageView which I want to show and hide (depending on the if's).
I've looked everywhere about how to do this and put it as many ways as I can into Google, but no luck.
This might be a baby step in Objective C, but please help as it will teach me.
Thanks in advance.
Declare an IBOutlet for the UIImageView in the header file:
#property (weak) IBOutlet UIImageView *myImageView;
After that, connect the UIImageView to this IBOutlet in Interface Builder.
Then, you can reference (and hide it) like:
self.myImageView.hidden = _ScreenOnOff;
in your implementation file.
See also: Creating and Connecting an Outlet
This action is probably owned by your view controller. If your view controller has a UIImageView property named 'imageView' you can access it from inside your action just like you're doing with the _ScreenOnOff.
To hide your image view you could do something like this:
self.imageView.hidden = YES;
Note that it is important to use self.imageView and self.ScreenOnOff instead of accessing directly the property by _imageView. When you declare a property in your class (be it an IBOutlet or not) the compiler synthesizes accessor methods to that property (get and sets). So when you call self.ScreenOnOff it would be the similar of doing [self ScreenOnOff].
The only places where you will access the property directly by '_' is inside init and dealloc methods. '- (void) viewDidLoad' is on type of init method. I guess you want something like this:
- (IBAction)screenButtonClicked:(id)sender {
UIButton *button = (UIButton *)sender;
if (self.ScreenOnOff) {
[self.view setBackgroundColor:[UIColor blackColor]];
[button setTitle:#"Screen (Off)" forState: UIControlStateNormal];
self.imageView.hidden = YES;
}
else {
[self.view setBackgroundColor:[UIColor whiteColor]];
[button setTitle:#"Screen (On)" forState: UIControlStateNormal];
self.imageView.hidden = NO;
}
self.ScreenOnOff = !self.ScreenOnOff;
}
I hope that helps.

How do I set and get UIButtons' tag?

How do I set a tag for a button programmatically?
I later want to compare to tags for a conclusion
I've tried this
-(IBAction)buttonPressed:(id)sender{
NSLog(#"%d", [sender tag]);
}
but that just crashes the app.
Any other ideas?
You need to cast sender as a UIButton:
-(IBAction)buttonPressed:(id)sender{
UIButton *button = (UIButton *)sender;
NSLog(#"%d", [button tag]);
}
Edit: Regarding the message "unrecognized selector"...
Based on your error message, it's not able to call the buttonPressed method in the first place. Notice in the error message it is looking for "buttonPressed" (no colon at end) but the method is named "buttonPressed:". If you are setting the button target in code, make sure the selector is set to buttonPressed: instead of just buttonPressed. If you are setting the target in IB, the xib may be out of sync with the code.
Also, your original code "[sender tag]" should also work but to access button-specific properties, you'll still need to cast it to UIButton.
I know this is an old question and been answered many a time in other questions, but it came up in a google search as second from the top. So, here is the answer to why it was crashing. Change it to 'button.tag'
-(void)myMethod
{
UIButton *theButton = [UIButton buttonWithType:UIButtonTypeCustom];
[theButton addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchDown];
theButton.tag = i;//or whatever value you want. In my case it was in a forloop
}
-(void)buttonPressed:(id)sender
{
UIButton *button = (UIButton *)sender;
NSLog(#"%d", button.tag);
}
No need for casting. This should work:
-(IBAction)buttonPressed:(UIButton*)sender
{
NSLog(#"%d", [sender tag]);
}

Resources