issue enabling dataDetectorTypes on a UITextView in a UITableViewCell - iphone

I have a UITextView inside a UITableViewCell in a table. "editable" for the UITextView is turned off, which allows me to set dataDetectorTypes to UIDataDetectorTypeAll, which is exactly what I want. The app now detects when the user touches a link in the UITextView, and does the appropriate thing.
The problem arises when the user touches on part of the UITextView where there is no link. I want the didSelectRowAtIndexPath in the UITableView delegate to be called. But it isn't, because the UITextView is trapping the touch, even when no link is detected.
My first guess was to turn userInteractionEnabled on the UITextView to NO. This means that didSelectRowAtIndexPath will get called, but then the UITextView can't detect links. It's a catch-22.
Any ideas on how to fix this?
Thanks for any help.

Maybe you could try passing the touch up the responder chain.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
}

Override all four of the UIResponder touch handlers to forward to the text view's superview.
The header file states that "Generally, all responders which do custom touch handling should override all four of these methods. … You must handle cancelled touches to ensure correct behavior in your application. Failure to do so is very likely to lead to incorrect behavior or crashes."
class MyTextView: UITextView {
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.superview?.touchesBegan(touches, withEvent: event)
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.superview?.touchesMoved(touches, withEvent: event)
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.superview?.touchesEnded(touches, withEvent: event)
}
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
self.superview?.touchesCancelled(touches, withEvent: event)
}
}

Related

Track fingers in UIViewController

I want to track down the position of my fingers in a UIViewController. I implemented this with the following function and this is working great!
override func viewDidLoad() {
view.userInteractionEnabled = true
view.multipleTouchEnabled = true
super.viewDidLoad()
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
//Create subview and place it under your finger.
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
//Here methods which tracks the moves of the finger and updates the subviews position.
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
//Remove subview from superview overhere.
}
I have two issues:
When I press more than 5 fingers on the screen, touchesBegin/touchesMoved/touchesEnded will not be called anymore. Even when I place 6 fingers and remove 1.
Sometimes touchesBegan is called from random positions on my screen. TouchesEnded is called for the same point after that.
Should I implement this on another way? I also tried it using UIGestureRecognizer but without success.
I added this function
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
}
And this is called when I tap the 6th finger on the screen.

Swift - view.endEditing in touchesBegan not working

I try to hide keyboard by pressing on any place of the screen. I use following code
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.view.endEditing(true)
}
But id doens't work, keyboard is not hiding.
How to use it correctly ?
Conform to UITextFieldDelegate
In your viewController() assign delegate of YOURTextField.delegate = self.
In your method use self.YOURTextField.resignFirstResponder()

Iterating over NSObject set as a certain type

I have a function that that receives a Set<NSObject> and I need to iterate over the set as a Set<UITouch>. How exactly do I test for this and unwrap the set?
override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch in touches {
// ...
}
}
Generally you would use a conditional cast to check each element
for its type. But here, the touches parameter is
documented
as
A set of UITouch instances that represent the touches that are moving
during the event represented by event.
therefore you can force-cast the entire set:
override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch in touches as! Set<UITouch> {
// ...
}
}
Note that in Swift 2 the function declaration changed to
func touchesMoved(_ touches: Set<UITouch>, withEvent event: UIEvent?)
(due to the "light-weight generics" in Objective-C) so that a cast is not needed anymore.
Use the as operator to perform type casting:
for touch in touches {
if let aTouch = touch as? UITouch {
// do something with aTouch
} else {
// touch is not an UITouch
}
}

Using Touchesbegan once

I have a touchesbegan and a touchesmoved that move a UIImageView around the screen. But I want to make it so I can't start moving around the screen then go to the opposite side using touchesbegan. I don't want to be able to just tap my way to other side. Is that even possible? Here's my code:
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
var touch : UITouch! = touches.anyObject() as UITouch
location = touch.locationInView(self.view)
Player.center = location
}
override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
var touch : UITouch! = touches.anyObject() as UITouch
location = touch.locationInView(self.view)
Player.center = location
}
Thanks.

Override UIGestureRecognizer touchesBegan

I have 1 Main View and 1 SubView:
Main View > SubView
I think that the Main View is "stealing" the events from the SubView.
For example, when I tap on the SubView, only the Main View GestureRecognizer is fire.
Here is my custom GestureRecognizer (which intercepts every touch event):
import UIKit
import UIKit.UIGestureRecognizerSubclass
class MainGestureRecognizer: UIGestureRecognizer {
override func touchesBegan(touches: NSSet!, withEvent event: UIEvent!) {
super.touchesBegan(touches, withEvent: event);
//nextResponder() ??
state = UIGestureRecognizerState.Began;
}
override func touchesMoved(touches: NSSet!, withEvent event: UIEvent!) {
super.touchesMoved(touches, withEvent: event);
//nextResponder() ??
state = UIGestureRecognizerState.Changed;
}
override func touchesEnded(touches: NSSet!, withEvent event: UIEvent!) {
super.touchesEnded(touches, withEvent: event);
//nextResponder() ??
state = UIGestureRecognizerState.Ended;
}
override func touchesCancelled(touches: NSSet!, withEvent event: UIEvent!) {
super.touchesCancelled(touches, withEvent: event);
//nextResponder() ??
state = UIGestureRecognizerState.Cancelled;
}
}
Maybe I should use nextResponder, but I have only found Obj-C code like:
[self.nextResponder touchesBegan:touches withEvent:event];
What's the trick to pass an event to the next responder in the responder chain?
Is there a way to pass touches through on the iPhone?
So the question is, what should I do to make the second event (the SubView Event) fire too?
Is there a function like nextResponder in Swift?
Ôh ! Here is the Swift code for nextResponder :
https://stackoverflow.com/a/26510277/4135158