Est-il possible d'effectuer une action personnalisée lorsque l'utilisateur touche un lien téléphonique auto-détecté dans UITextView. Ne conseillez pas d'utiliser plutôt UIWebView.
Et s'il vous plaît ne répétez pas simplement le texte de la référence des classes Apple - certainement je l'ai déjà lu.
Merci.
Mise à jour: De ios10 ,
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction;
De ios7 et Ultérieur UITextView
a la méthode déléguée:
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange *NS_DEPRECATED_IOS(7_0, 10_0, "Use textView:shouldInteractWithURL:inRange:forInteractionType: instead");*
pour intercepter les clics sur les liens. Et c'est la meilleure façon de le faire.
Pour ios6 et les versions antérieures, une bonne manière de procéder consiste à sous-classer UIApplication
et à écraser la -(BOOL)openURL:(NSURL *)url
@interface MyApplication : UIApplication {
}
@end
@implementation MyApplication
-(BOOL)openURL:(NSURL *)url{
if ([self.delegate openURL:url])
return YES;
else
return [super openURL:url];
}
@end
Vous devrez implémenter openURL:
dans votre délégué.
Maintenant, pour que l'application démarre avec votre nouvelle sous-classe de UIApplication
, localisez le fichier main.m dans votre projet. Dans ce petit fichier qui initialise votre application, il y a généralement cette ligne:
int retVal = UIApplicationMain(argc, argv, nil, nil);
Le troisième paramètre est le nom de la classe pour votre application. Donc, remplacer cette ligne pour:
int retVal = UIApplicationMain(argc, argv, @"MyApplication", nil);
Cela a fait le tour pour moi.
Dans iOS 7 ou version ultérieure
Vous pouvez utiliser la méthode de délégué UITextView suivante:
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
La vue texte appelle cette méthode si l'utilisateur appuie ou appuie de manière prolongée sur le lien URL. L'implémentation de cette méthode est facultative. Par défaut, la vue texte ouvre l'application chargée de gérer le type d'URL et lui transmet l'URL. Vous pouvez utiliser cette méthode pour déclencher une action alternative, telle que l'affichage du contenu Web à l'URL dans un affichage Web de l'application en cours.
Important:
Les liens dans les vues texte ne sont interactifs que si la vue texte est sélectionnable mais non éditable. C'est-à-dire si la valeur de UITextView la propriété sélectionnable est YES et la propriété isEditable est NO.
Version rapide:
Votre configuration UITextView standard devrait ressembler à quelque chose comme ceci, n'oubliez pas le délégué et les types de données.
var textView = UITextView(x: 10, y: 10, width: CardWidth - 20, height: placeholderHeight) //This is my custom initializer
textView.text = "dsfadsaf www.google.com"
textView.selectable = true
textView.dataDetectorTypes = UIDataDetectorTypes.Link
textView.delegate = self
addSubview(textView)
Après la fin de votre classe, ajoutez cette pièce:
class myVC: UIViewController {
//viewdidload and other stuff here
}
extension MainCard: UITextViewDelegate {
func textView(textView: UITextView, shouldInteractWithURL URL: NSURL, inRange characterRange: NSRange) -> Bool {
//Do your stuff over here
var webViewController = SVModalWebViewController(URL: URL)
view.presentViewController(webViewController, animated: true, completion: nil)
return false
}
}
Pour Swift 3
textView.delegate = self
extension MyTextView: UITextViewDelegate
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
GCITracking.sharedInstance.track(externalLink: URL)
return true
}
}
ou si la cible est> = IOS 10
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool
Avec Swift 3 et i0S 10, le moyen le plus simple d’interagir avec des numéros de téléphone, des URL ou des adresses dans UITextView
est d’utiliser UIDataDetectorTypes
. Le code ci-dessous montre comment afficher un numéro de téléphone dans une UITextView
afin que l'utilisateur puisse interagir avec ce numéro.
import UIKit
class ViewController: UIViewController {
// Link this outlet to a UITextView in your Storyboard
@IBOutlet weak var textView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
textView.text = "+33687654321"
textView.isUserInteractionEnabled = true // default: true
textView.isEditable = false // default: true
textView.isSelectable = true // default: true
textView.dataDetectorTypes = [.phoneNumber]
}
}
Avec ce code, lorsque vous cliquez sur le numéro de téléphone, une UIAlertController
apparaîtra.
Vous pouvez également utiliser NSAttributedString
:
import UIKit
class ViewController: UIViewController {
// Link this outlet to a UITextView in your Storyboard
@IBOutlet weak var textView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
let phoneUrl = NSURL(string: "tel:+33687654321")! // "telprompt://+33687654321" also works
let attributes = [NSLinkAttributeName: phoneUrl]
let attributedString = NSAttributedString(string: "phone number", attributes: attributes)
textView.attributedText = attributedString
textView.isUserInteractionEnabled = true // default: true
textView.isEditable = false // default: true
textView.isSelectable = true // default: true
}
}
Avec ce code, lorsque vous cliquez sur la chaîne attribuée, une UIAlertController
apparaîtra.
Toutefois, vous souhaiterez peut-être effectuer une action personnalisée au lieu de faire apparaître une UIAlertController
lorsque vous cliquez sur un numéro de téléphone. Vous pouvez également garder une variable UIAlertController
pour qu'elle apparaisse et exécute votre propre action personnalisée dans le même temps.
Dans les deux cas, vous devrez rendre votre UIViewController
conforme au protocole UITextViewDelegate
et implémenter textView(_:shouldInteractWith:in:interaction:)
. Le code ci-dessous montre comment faire.
import UIKit
class ViewController: UIViewController, UITextViewDelegate {
// Link this outlet to a UITextView in your Storyboard
@IBOutlet weak var textView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
textView.delegate = self
textView.text = "+33687654321"
textView.isUserInteractionEnabled = true
textView.isEditable = false
textView.isSelectable = true
textView.dataDetectorTypes = [.phoneNumber]
}
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
/* perform your own custom actions here */
print(URL)
return false // return true if you still want UIAlertController to pop up
}
}
Avec ce code, lorsque vous cliquez sur le numéro de téléphone, aucune UIAlertController
n'apparaîtra et vous obtiendrez l'impression suivante dans votre console:
tel: +33687654321
J'ai un contenu dynamique en mode texte, qui peut contenir un lien. ShouldInteractWithURL est appelé uniquement lorsque l'utilisateur appuie longuement sur le lien mais n'appelle pas au robinet S'il vous plaît rediriger si un ami a une référence à elle.
Voici quelques extraits du code.
UITextView *ltextView = [[UITextView alloc] init];
[ltextView setScrollEnabled:YES];
[ltextView setDataDetectorTypes:UIDataDetectorTypeLink];
ltextView.selectable = YES;
[ltextView setEditable:NO];
ltextView.userInteractionEnabled = YES;
ltextView.delegate = (id)self;
ltextView.delaysContentTouches = NO;
[self.view addsubview:ltextview];
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange{
[self.mActionDelegate userClickedOnImageLinkFromWebview:URL];
NSLog(@"urls is :- %@",URL);
return FALSE;
}
La méthode déléguée ci-dessus n'est pas appelée au robinet.
Cordialement, Rohit Jankar
application:handleOpenURL:
est appelé lorsqu'une autre application ouvre votre -app application en ouvrant une URL avec un modèle que votre application prend en charge. Il n'est pas appelé lorsque votre application commence à ouvrir une URL.
Je pense que la seule façon de faire ce que Vladimir veut est d'utiliser un UIWebView au lieu d'un UITextView. Amenez votre contrôleur de vue à implémenter UIWebViewDelegate, définissez le délégué de UIWebView sur le contrôleur de vue, puis implémentez webView:shouldStartLoadWithRequest:navigationType:
dans le contrôleur de vue pour ouvrir [request URL]
au lieu de quitter votre application et de l'ouvrir dans Mobile Safari.
Je n'ai pas essayé moi-même, mais vous pouvez essayer d'implémenter la méthode application:handleOpenURL:
dans votre délégué d'application. Il semble que toutes les demandes openURL
passent par ce rappel.
Vous ne savez pas comment vous allez intercepter la liaison de données détectée, ni quel type de fonction vous devez exécuter. Mais vous pourrez peut-être utiliser la méthode textField didBeginEditing pour exécuter un test/une analyse du champ de texte si vous savez ce que vous cherchez. ou commencez par "www." pour saisir ces champs, mais vous auriez besoin d'écrire un petit code pour scruter la chaîne de champs de texte, reconstituer ce dont vous avez besoin, puis l'extraire pour l'utilisation de votre fonction. Je ne pense pas que ce serait si difficile, une fois que vous avez précisé exactement ce que vous vouliez, puis que votre instruction if () a été filtrée selon un modèle de correspondance très spécifique de ce dont vous aviez besoin.
Bien entendu, cela implique que l'utilisateur va toucher la zone de texte afin d'activer didBeginEditing (). Si ce n'est pas le type d'interaction utilisateur que vous recherchez, vous pouvez simplement utiliser un minuteur de déclenchement, qui commence par ViewDidAppear () ou un autre système en fonction des besoins, puis parcourt la chaîne de champs de texte, puis la fin méthodes que vous avez construites, il vous suffit de désactiver le minuteur.
Swift 4:
1) Créez la classe suivante (UITextView sous-classe):
import Foundation
protocol QuickDetectLinkTextViewDelegate: class {
func tappedLink()
}
class QuickDetectLinkTextView: UITextView {
var linkDetectDelegate: QuickDetectLinkTextViewDelegate?
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let glyphIndex: Int? = layoutManager.glyphIndex(for: point, in: textContainer, fractionOfDistanceThroughGlyph: nil)
let index: Int? = layoutManager.characterIndexForGlyph(at: glyphIndex ?? 0)
if let characterIndex = index {
if characterIndex < textStorage.length {
if textStorage.attribute(NSLinkAttributeName, at: characterIndex, effectiveRange: nil) != nil {
linkDetectDelegate?.tappedLink()
return self
}
}
}
return nil
}
}
2) Où que vous configuriez votre textview, procédez comme suit:
//init, viewDidLoad, etc
textView.linkDetectDelegate = self
//outlet
@IBOutlet weak var textView: QuickDetectLinkTextView!
//change ClassName to your class
extension ClassName: QuickDetectLinkTextViewDelegate {
func tappedLink() {
print("Tapped link, do something")
}
}
Si vous utilisez le storyboard, assurez-vous que la vue texte ressemble à ceci dans l'inspecteur d'identité du volet de droite:
Voilà! Maintenant, vous obtenez le lien appuyez immédiatement après le lien au lieu de l'URL shouldInteractWith, méthode d'URL