I have a UIWebView in which I've implemented a single tap gesture recognizer. I don't have any recognizer for long hold, though my problem is in making a selection. Issues:
Select some text in a UIWebView, select copy from contextual menu. Menu should disappear.
Long hold to make a text selection, single tap gesture is also getting called.
If text is selected, a single tap elsewhere should remove the selection like in Safari.
…
func createGestureRecognizer() {
// single tap
let singleTapGesture = UITapGestureRecognizer(target: self, action: "handleSingleTap:")
singleTapGesture.numberOfTapsRequired = 1
singleTapGesture.delegate = self
singleTapGesture.cancelsTouchesInView = false
webView.addGestureRecognizer(singleTapGesture)
}
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
if touch.view.isDescendantOfView(self.webView) {
return true
}
return true
}
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if otherGestureRecognizer.isKindOfClass(UITapGestureRecognizer) {
otherGestureRecognizer.requireGestureRecognizerToFail(gestureRecognizer)
// println("added failure requirement to: \(otherGestureRecognizer)")
}
return true
}
func handleSingleTap(tap: UITapGestureRecognizer) {
…
}
EDIT: It is sort of working. Problem: Making an initial text selection requires a longer hold than normal. A normal long hold that would normally make a selection calls my single tap recognizer without selecting any text.
func handleSingleTap(tap: UITapGestureRecognizer) {
let selection = webView.stringByEvaluatingJavaScriptFromString("window.getSelection().toString()")!
if selection == "" {
// do stuff
} else {
webView.userInteractionEnabled = false
webView.userInteractionEnabled = true
webView.stringByEvaluatingJavaScriptFromString("window.getSelection().removeAllRanges()")
}
Related
I have a view that added some UIButton.
given a CGPoint how can I get the button laid on.
sample code
let location = tapRecognizer.location(in: view)
let tapView = view.hitTest(location, with: nil)
the code below won't work how can I get the UIbutton form tapView
if let button = tapView as? UIButton {
print("text")
}
help appreciated
While adding button to the view add target to the button and assign a different tag to each button and perform action according to the tag
For the this purpose you can use the gesture delegate like
Example:-
func addGestureOnContentView () -> Void {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ExploreViewController.hideTableView))
tapGesture.delegate = self
self.view.addGestureRecognizer(tapGesture)
}
Now use gesture delegate like :-
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
if gestureRecognizer is UITapGestureRecognizer {
if (touch.view?.isDescendant(of: UIButton))! {
return false //Perform your task in this block
}
}
return true
}
I have a table view with cells that the user can swipe to delete the row. I'm receiving a fatal error: Index out of range error whenever I swipe two rows at once (with two fingers, one on each row).
I've added these 4 lines in my OrdersViewController:
override func viewDidLoad() {
...
self.view.isMultipleTouchEnabled = false
self.view.isExclusiveTouch = true
self.ordersTable.isMultipleTouchEnabled = false
self.ordersTable.isExclusiveTouch = true
}
in an effort to try to change this behavior so that only one cell is swiped at a time, but nothing has changed. I can still use two fingers on two different rows to swipe back and forth at the same time.
Is there another way?
None of the IsExclusiveTouch and IsMultipleTouchEnabled is working regardless of where I put it. I wonder if it has anything to do with me using this library github.com/alikaragoz/MCSwipeTableViewCell
It could also be because I'm using Firebase?
First of all set delegates of gesture and then use this delegate, it could help you :
override func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return false;
}
I eventually did this, using the callbacks made available by the table cell pod i'm using:
class OrderTableManager {
static var swiping = false
}
class OrderPreparingTableViewCell: MCSwipeTableViewCell, MCSwipeTableViewCellDelegate {
override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if !OrderTableManager.swiping {
OrderTableManager.swiping = true
return true
} else {
return false
}
}
// MARK: Public
func swipeTableViewCellDidEndSwiping(_ cell: MCSwipeTableViewCell!) {
OrderTableManager.swiping = false
}
func displayOrder(order: AppState.Order, clock: Clock, fDone: #escaping SwipeHandler, fDelete: #escaping SwipeHandler) -> OrderPreparingTableViewCell {
...
self.delegate = self
...
}
I don't know how exactly to achieve the following in Swift:
I am displaying a modal form sheet popup in my iPad app. In order to dismiss this view I have added a button that dismisses it. But what I really want is for it to dismiss when you click outside of the view. Almost the same behaviour as the popover. I have tried achieving this by adding tap gestures, making it a popover, any of the presentation styles, nothing works.
Has someone maybe done this so that you can point me in the right direction?
I had to display some screens like a popup in my app, so I've made a
base class that looks like this:
class MyBasePopUp: UIViewController, UIGestureRecognizerDelegate {
var tap: UITapGestureRecognizer!
override func viewDidAppear(_ animated: Bool) {
tap = UITapGestureRecognizer(target: self, action: #selector(onTap(sender:)))
tap.numberOfTapsRequired = 1
tap.numberOfTouchesRequired = 1
tap.cancelsTouchesInView = false
tap.delegate = self
self.view.window?.addGestureRecognizer(tap)
}
internal func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
internal func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
let location = touch.location(in: self.view)
if self.view.point(inside: location, with: nil) {
return false
}
else {
return true
}
}
#objc private func onTap(sender: UITapGestureRecognizer) {
self.view.window?.removeGestureRecognizer(sender)
self.dismiss(animated: true, completion: nil)
}
This is just to dismiss the popup, be careful if you have multiple gestures.
The google login button provided by google (GIDSignInButton), is not working in normal press but in long press. Otherwise evrything is normal.
Any idea guys?
That was due to a tap recognizer I had in the same viewcontroller. Issue got solved.
Google sign in default button not works in single tap, it works after 1
long press because of the Tap Gesture included in same
viewcontroller...
So the Solution is Handle touch event in sameViewcontroller:
override func viewDidLoad() {
super.viewDidLoad()
let touchRecognizer = UITapGestureRecognizer(target: self, action:
#selector(onBaseTapOnly))
touchRecognizer.numberOfTouchesRequired = 1
touchRecognizer.delegate = self
self.view.addGestureRecognizer(touchRecognizer)
}
func onBaseTapOnly(sender: UITapGestureRecognizer) {
if sender.state == .ended {
//react to tap
self.view.endEditing(true)
}
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
shouldReceive touch: UITouch) -> Bool {
return touch.view == gestureRecognizer.view
}
I am using this code to dismiss keyboard when user click's outside the TextField
override func viewDidLoad() {
...
let tapGesture = UITapGestureRecognizer(target: self, action: "tap:")
view.addGestureRecognizer(tapGesture)
...
}
func tap(gesture: UITapGestureRecognizer) {
txtName.resignFirstResponder()
}
It is working when the user click's anywhere outside the textfield but the datepicker. When he put's a name and then click on the DatePicker (just click, not roll) the tap is not recognized.
What should I do to make it work?
It's possible the gesture recogniser on the DatePicker is interfering with yours. See if modifying this function helps your case.
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true //Obviously think about the logic of what to return in various cases
}