Dans une application iOS 7, j'ai un UITextView
avec un lien, mais appuyer sur le lien ne se déclenche pas. Il ne répond qu'à un "tap and hold" gênant. Je veux qu'il réponde dès qu'un utilisateur appuie dessus, comme le fonctionnement d'un lien UIWebView
lien. Voici ma configuration:
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:@"Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."];
[text addAttribute:NSLinkAttributeName value:@"myurl://tapped" range:NSMakeRange(6, 16)];
self.textView.attributedText = text;
self.textView.editable = NO;
self.textView.delaysContentTouches = NO;
}
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
{
if ([[URL scheme] isEqualToString:@"myurl"])
{
// Handle tap
return NO;
}
return YES;
}
La Apple Documentation de la méthode shouldInteractWithURL
indique: "La vue texte appelle cette méthode si l'utilisateur appuie ou appuie longuement sur le lien URL". La pression longue fonctionne, mais le robinet ne semble pas fonctionner.
Est-ce que quelqu'un sait comment obtenir ceci pour répondre immédiatement?
Le UITextView
est-il sélectionnable?. Essayez avec:
self.textView.selectable = YES;
Éditer:
Je commence à penser que peut-être un appui long est le seul moyen de le tirer contrairement à ce que Apple dit. Vérifiez cela lien , peut-être que cela aidera.
Si vous souhaitez toujours utiliser un UITextView
natif, vous pouvez ajouter un identificateur de prise à votre affichage de texte et obtenir les attributs de chaîne à l'emplacement de prise. Lorsque vous trouvez un lien, vous pouvez l'ouvrir immédiatement.
J'ai écrit un Gist qui résout cela pour iOS 7/8. C'est une extension légère de UITextView
qui transmet également -[UITextViewDelegate textView:shouldInteractWithURL:inRange:]
et expose le module de reconnaissance interne des gestes de prise.
https://Gist.github.com/benjaminbojko/c92ac19fe4db3302bd28
Voici un petit exemple:L'exemple ci-dessous ne fonctionne que sur iOS 8. Voir l'essentiel ci-dessus pour la prise en charge d'iOS 7 + 8.
Ajoutez votre reconnaissance de robinet:
// ...
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tappedTextView:)];
[myTextView addGestureRecognizer:tapRecognizer];
myTextView.selectable = YES; // otherwise the gesture won't recognize
// ...
Et ajoutez votre rappel:
- (void)tappedTextView:(UITapGestureRecognizer *)tapGesture {
if (tapGesture.state != UIGestureRecognizerStateEnded) {
return;
}
UITextView *textView = (UITextView *)tapGesture.view;
CGPoint tapLocation = [tapGesture locationInView:textView];
UITextPosition *textPosition = [textView closestPositionToPoint:tapLocation];
NSDictionary *attributes = [textView textStylingAtPosition:textPosition inDirection:UITextStorageDirectionForward];
NSURL *url = attributes[NSLinkAttributeName];
if (url) {
[[UIApplication sharedApplication] openURL:url];
}
}
Et Swift version:
Reconnaissance du robinet:
let tapRecognizer = UITapGestureRecognizer(target: self, action: Selector("tappedTextView:"))
myTextView.addGestureRecognizer(tapRecognizer)
myTextView.selectable = true
Rappeler:
func tappedTextView(tapGesture: UIGestureRecognizer) {
let textView = tapGesture.view as! UITextView
let tapLocation = tapGesture.locationInView(textView)
let textPosition = textView.closestPositionToPoint(tapLocation)
let attr: NSDictionary = textView.textStylingAtPosition(textPosition, inDirection: UITextStorageDirection.Forward)
if let url: NSURL = attr[NSLinkAttributeName] as? NSURL {
UIApplication.sharedApplication().openURL(url)
}
}
Comme l'a mentionné nnarayann, CCHLinkTextView évite le problème de la reconnaissance de prise retardée. Cette bibliothèque implémente son propre identificateur de gestes et est désormais disponible en version 1.0.
Swift 4 solution
isSelectable
soit true
ou false
, cela fonctionnelet tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleLinkTap(_:)))
textView.addGestureRecognizer(tapRecognizer)
@objc func handleLinkTap(_ recognizer: UITapGestureRecognizer) {
let tapLocation = recognizer.location(in: textView)
guard
let textPosition = textView.closestPosition(to: tapLocation),
let url = textView.textStyling(at: textPosition, in: .forward)?[NSAttributedStringKey.link.rawValue],
let urlString = (url as? String) ?? (url as? URL)?.absoluteString,
urlString == "myurl"
else { return }
let url = URL(string: urlString)!
// Do whatever you want with this URL, such as
UIApplication.shared.openURL(url)
}
Parfois, cela ne fonctionne pas sur le simulateur iOS ou ne fonctionne que si vous maintenez votre doigt appuyé.
Vous devez le tester sur un vrai appareil.
Et n'oubliez pas de le définir selectable
.
Avez-vous essayé de définir textview.delaysContentTouches = NO;
? Cela pourrait peut-être aider.
S'il n'y a aucune raison pressante d'utiliser un UITextView
, tel qu'il y a un autre texte affiché, vous pouvez utiliser un UILabel
combiné avec un UITapGestureRecognizer
pour obtenir l'effet vous cherchez.
Sinon, vous pourriez plutôt utiliser un UIWebView
réel.