Exclusive touch on UIControl - ios

I have an UIButton and UISwitch. A user could touch both with one finger each at the same time and release - triggering 2 separate TouchUpInside #IBActions.
How can I tell a control that it's touches must be exclusive, without creating a subclass?

UIControl is subclass of UIView so you can directly set exclusiveTouch = true on any UI control.

Related

Touch down on UITapGestureRecogniser

Is it possible to setup UITapGestureRecogniser for touch down event? Default is touch up...
No, that's not possible, but it shouldn't be hard to subclass UIGestureRecognizer to create your own recognizer that does that.
You could also use a UILongPressGestureRecognizer with the minimumPressDuration property set to 0.0. Note however that your action will then be called continuously when the touch moves, so make sure to check that the state of the recognizer is UIGestureRecognizerStateBegan in the action (this will only be once).
A tap gesture recogniser detects a tap. This is different from touch up.
The best way to detect a touch down is to write your own touchesBegan method in the custom UIView or UIViewController.

Objective-C - addToSubview but do not intercept touches

Is there a way you can add a UIView without the view intercepting touches? I tried insertSubview: belowSubview
The reason I want to do this is because I'm adding a UITextField to a UITableViewCell's contentView. But I don't want the UITextField intercepting the touches when I select a row. I know I can set the UITextField userInteractionEnabled property to NO but this leads to a lot of micro management.
Override canBecomeFirstResponder to return NO.
See this info on the Responder Chain.

Using a UIView as a button

I'm trying to use a UIView I've created in Storyboard as a button. I assumed it would be possible to use a UIButton, setting the type to custom. However I was unable to add subviews to a custom UIButton in Storyboard.
As such I've just spent the last hour reinventing the wheel by making my own custom gesture recoginizers to reimplement button functionality.
Surely this isn't the best way of doing it though, so my question - to more experienced iOS developers than myself - is what is the best way to make a custom button?
To be clear it needs to:
Use the UIView I've created as it's hittable area.
Be able to show a
different state depending on whether is currently highlighted or not
(i.e. touch down).
Perform some action when actually tapped.
Thank you for your help.
You can use a UIButton, set the type to custom, and then programmatically add your subviews...
Change your UIView into a UIControl in the storyboard. Then use the method [controlViewName addTarget:self action:#selector(*click handler method*) forControlEvents:UIControlEventTouchDown];. click handler method is a placeholder for the method name of your handler. Use this method except change out the UIControlEventTouchDown for UIControlEventTouchInside and UIControlEventTouchDragExit to call a method when the user finishes their click and drags their finger out of the view respectively. I used this for something I'm working on now and it works great.
In Touch down you will want to: highlight all subviews
In Touch up inside you will want to: unhighlight all subviews and perform segue or do whatever the button is supposed to do
In Touch Drag Exit you will want to: unhighlight all subviews
See second answer by LiCheng in this similiar SO post.
Subclass UIControl instead. You can add subviews to it and it can respond to actions
Why are you implementing your own GestureRecognizer? I recommend using the UIView so you can add subviews in the interface builder and adding a UITapGestureRecognizer. You can even do this graphically since you don't care about IOS4 support.

UITextField subview of UIImageView is not responding to touch events

I have a UITextField that responds to touch events when it is added as a subview of self.view. When I add it as a subview of a UIImageView it does not respond to touch events any more. I make it a firstResponder and the field is active and takes keyboard input still. Any ideas what is wrong?
The docs for UIImageView state:
New image view objects are configured to disregard user events by default. If you want to handle events in a custom subclass of UIImageView, you must explicitly change the value of the userInteractionEnabled property to YES after initializing the object.
Try setting imgView.userInteractionEnabled = YES
If this doesn't work, I would try adding the UIImageView and the UITextField in a UIView instead. Anyway, this approach seems cleaner.

Managing events on a custom UIControl

I am subclassing UIControl to compose a custom control that contains different standard controls.
For this discussion let's assume that my custom UIControl contains a UIButton only.
What I would like to achieve is that clicking anywhere in the custom UIControl generates a click event for that custom UIControl. The standard behavior is that the UIButton will process and consume (i.e. not forward) the click event.
As subclassing UIButton is discouraged, I can't really find a straightforward way of achieving this.
Any suggestions?
I came up with a simple solution that doesn't need subclassing of the UIButton.
In the action method defined for the UIButton's TouchUpInside control event, I have added the following line of code:
[self sendActionsForControlEvents:UIControlEventTouchUpInside];
This results in the TouchUpInside control event being called, when clicking anywhere in the custom UIControl.
UIViews have a method called -hitTest:withEvent: that the event system uses to crawl the view hierarchy and dispatch events to subviews. If you want a parent view to gobble up all events that might otherwise be dispatched to its subviews, just override the parent's -hitTest:withEvent: with something like the following:
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
if(CGRectContainsPoint([self bounds], point)){
return self;
}
return [super hitTest:point withEvent:event];
}
UIButton is designed to process touch events. You can either set userInteractionEnabled to NO to have the button not accept any touches, or you can use addTarget:action:forControlEvents: on the button to have it call a method on your class when the button is touched.
BTW, where is subclassing UIButton discouraged?
Often I find useful user interaction related tasks in UIResponder class, which is the super class of UIControl - UIButton.
Read about – touchesBegan:withEvent:, – touchesMoved:withEvent:, – touchesEnded:withEvent:, – touchesCancelled:withEvent: in http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIResponder_Class/Reference/Reference.html You may find ways to customize user interaction for your UIButton. By the way, I don't think there will be any problem subclassing UIButton, no matter what you've heard, as long as your implementation is correctly added to the super class implementation, or does responsibly override it altogether.

Resources