Tap gesture on UILabel beside a UIPageControl not working - swift

I have a UILabel on both sides of a UIPageControl, as pictured below:
I found that tapping on the sides of the UIPageControl the dot would progress, ie not on my arrows and not triggering a method of mine. But nothing else would change, so I set isUserInteractionEnabled to false on the UIPageControl.
I connected (via UITapGestureRecognizer) another UILabel above and it launches a method fine.
However the UILabels, beside the UIPageControl, will not work. NOTE: I do have isUserInteractionEnabled set to true on this element. (I even temporarily changed the element to a UIButton and it wouldn't work either - so I reverted back to my UILabel.)
So, is there a way to add a UILabel to the side of a UIPageControl that gets triggered? Alternately, can the invisible objects (while tapping on the left or right of the UIPageControl - like in my second sentence) be connected to a custom method?
UPDATE:
I've added another separate modal (same title label, buttons, but no collection view and no page control). Again it won't respond when I press the label in the centre, but I temporarily am using the title label which responses and launches my method fine.
Can anyone say why?

I solved the issue!
I was declaring most variables - as well as the UILabel - in closures blocks, at the top of the class, like below:
let myLabel: UILabel = {
{
let view = UILabel()
view.translatesAutoresizingMaskIntoConstraints = false
view.isUserInteractionEnabled = true
view.textColor = UIColor.blue
return view
}
Within this closure I had view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(doMyLabelMethod(_:)))) and view.isUserInteractionEnabled = true, when I moved them out of the closure and placed them directly above addSubview(myLabel) it fired fine.
So variable-closures are good to contain many dressing, but not gesture recognizers!

Related

TapGesturecognizer not working in backgroundview in iphone X 12.1

I have a simple code to add tapgestureRecognizer to dismis ViewController when tap in screen, but it not working only in iPhone X 12.1.
addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(closeSharing(_:))))
Note: magicaly, when i add tap gesturecognizer to a new view that constraint equal to view that also not working, but if i constraint the new view not equal to view, that working. Does any one know why?.
You might need to check a couple of things here:
First step make sure that your main view is not covered for example of another top view which will break your tap gesture, so add the gesture to your top view.
Second step Make sure your view that will have the gesture should have the property view.isUserInteractionEnabled = true, otherwise the gesture will not work.
Third step Make sure your view appears when your testing, you might have a problem with constraints, so the view is out of screen bounds, so try giving the view a backgroundColor = .red to see if it exists or not, or you can use View Debugger from xCode.
Example of a working gesture:
let viewToDismiss = UIView(frame:UIScreen.main.bounds)
viewToDismiss.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(closeSharing(_:)))
tap.numberOfTapsRequired = 1
viewToDismiss.addGestureRecognizer(tap)

Detecting UIButton tap for button inside of tappable view

I have a container view with a button over it which hides and shows the view. Within the shown view, there are N number of mini buttons that have actions.
The problem I'm having is, when I tap on the mini buttons, those targets are ignored and the larger view button is what receives the action.
How do I configure things so that the larger tappable button on the view still works in most places but where the mini buttons exist, those tap actions register as well?
Thanks!
There are two possible solution
First
Change view hierarchy of uibutton (large on top of the stack in
interface builder)
Like
-Largebutton
-minibutton1
-minibutton1
'
'
-minibuttonn
Second one
Use gesture on the conainer view like
let hideViewGesture = UITapGestureRecognizer(target: self, action: "hideView")
containerView.addGestureRecognizer(hideViewGesture)
func hideView() {
containerView.isHidden = true
}
Its not merely possible to get button action working within a button as
1) Adding a button [Large button] on ContainerView will cause always to detect Large button action and will not allow you to detect button inside it
2) If seen in case of layers large button layer is on top So Logically always large button will first come in Action not inside View of containerView
Possible Solutions :
1) try to make use of gestures on ContainerView
2) you can use a segmented control as show and hide or a UIButton that is placed on side of containerView not over it So you will be able to perform all the required Actions
This is an old question but there actually is a simple solution, by overriding hitTest(_ point: CGPoint, with event: UIEvent?).
Inside your outer button:
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if self.innerButton.frame.contains(point) {
return self.innerButton
}
else if self.bounds.contains(point) {
return self
}
else {
return super.hitTest(point, with: event)
}
}
It tests to see if the touch point is within the inner button (or you could have several inner buttons), if so it returns it and the touch is registered only by the inner button, if not it goes to the outer view. If neither view contains it, it calls super so the touch is handled correctly by other views.

isUserInteractionEnabled = false still allows double tap gesture

I have created a double tap gesture for my Collection View. When a cell in the Collection View is double tapped i disable user interaction to the cell. This stops me being able to single tap that cell while a process runs. However i can still double tap that cell which runs the process again. I still want double tap to be available for other cells in the collection, i just want to disable it for the cell that is running process. When the process is finished user interaction is turned back on, and hopefully double tap also.
So this is how i define double tap, in viewDidLoad of the View Controller holding the Collection View:
// add gesture recogniser
let doubleTap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didDoubleTap))
doubleTap.numberOfTapsRequired = 2
doubleTap.delaysTouchesBegan = true
self.collectionView.addGestureRecognizer(doubleTap)
And I'm just switching userInteraction as usual when needed depending on state of process.
cell.isUserInteractionEnabled = false
cell.isUserInteractionEnabled = true
Im not sure how to approach this as if i disable the double tap gesture for the Collection View i cant double tap other cells. And i don't even know how to set it up so that double tap is only available in the cell and not the Collection View.
Disabling isUserInteractionEnabled on any subview of your collectionView will still pass events to the collectionView (superview). So isUserInteractionEnabled disables touch events on all subviews but not on superviews, which in this case is the collectionView.
You have a few options to proceed:
Create a custom UICollectionViewCell and add a UITapGestureRecognizer to handle the double tap internally and then delegate the double tap event.
Within the didDoubleTap method check to see if the cell that you just double tapped is enabled/disabled. You can do this by using indexPathForItemAtPoint: and then cellForItemAtIndexPath:.
You could set isEnabled to false on the gesture recognizer.
You could implement UIGestureRecognizerDelegate and return false from gestureRecognizerShouldBegin.

How to Disable Multi Touch on UIBarButtonItems & UI Buttons?

My app has quite a few buttons on each screen as well as a UIBarButtonItem back button and I have problems with people being able to multi click buttons. I need only 1 button to be clickable at a time.
Does anyone know how to make a UIBarButtonItem back button exclusive to touch?
I've managed to disable multi clicking the UIButtons by setting each one's view to isExclusiveTouch = true but this doesn't seem to count for the back button in the navigation bar.
The back button doesn't seem to adhere to isExclusiveTouch.
Does anyone have a simple work around that doesn't involve coding each and every buttons send events?
Many Thanks,
Krivvenz.
you can enable exclusive touch simply this will stop multiple touch until first touch is not done
buttton.exclusiveTouch = true
You could write an extension for UIBarButtonItem to add isExclusiveTouch?
you can simply disable the multi-touch property of the super view. You can also find this property in the storyboard.
you could try this for the scene where you want to disable multiple touch.
let skView = self.view as! SKView
skView.isMultipleTouchEnabled = false
I have found a solution to this. isExclusiveTouch is the solution in the end, but the reason why this property didn't do anything is because you need to set it also on all of the subviews of each button that you want to set as isExclusiveTouch = true. Then it works as expected :)
It's working fine in Swift
self.view.isMultipleTouchEnabled = false
buttonHistory.isExclusiveTouch = true
In addition of #Luky LĂ­zal answer, you need pay attention that all subviews of a view you want disable multi-touching (exactly all in hierarchy, actually subviews of subviews) must be set as isExclusiveTouch = true.
You can run through all of them recursively like that:
extension UIView
{
func allSubViews() -> [UIView] {
var all: [UIView] = []
func getSubview(view: UIView) {
all.append(view)
guard view.subviews.count > 0 else { return }
view.subviews.forEach{ getSubview(view: $0) }
}
getSubview(view: self)
return all
}
}
// Call this method when all views in your parent view were set
func disableMultipleTouching() {
self.isMultipleTouchEnabled = false
self.allSubViews().forEach { $0.isExclusiveTouch = true }
}

TapGestureRecognizer not firing in swift

Hi I'm having no cards to used to fixed this. Here we go.
I have this five imageview this is the declaration of first imageview but basically they have same declaration
#IBOutlet weak var first: UIImageView!{
didSet{
first.tag = 1
first.addGestureRecognizer(tapGesture())
}
}
and Then the tapGesture() method is this
private func tapGesture() -> UITapGestureRecognizer {
let tapGesture = UITapGestureRecognizer(target: self, action: Selector("iconTapped:"))
tapGesture.numberOfTapsRequired = 1
tapGesture.numberOfTouchesRequired = 1
return tapGesture
}
the action when the imageview is tapped the iconTapped() method is called, this is the code
func iconTapped(sender:UITapGestureRecognizer){
if let tag = sender.view?.tag{
processGesture(tag)
}
}
I have put all imageview userInteractionEnable to true but still not firing. Could anyone help me?
Some factor may or may not help, inside the viewdidload I update constraints and do some animation to imageview, but I'm not adding any subview programmatically
after trying so many things, I look on my view hierarchy and figure out that the parent view where my UIImageView rest userInteractionEnable is set to false(unchecked) in storyboard.
in this case the parentview is my superview, to fixed that I need to add this in viewDidLoad()
self.view.userInteractionEnabled = true
or
click the parentView in storyboard and in attributes inspector check the User Interaction Enable.
ps. sorry for silly mistake but I'll keep this question posted there might be other encountering same problem.