iphone objective-c uitextview datadetectortypes

iphone - Cómo interceptar hacer clic en el enlace en UITextView?



objective-c datadetectortypes (10)

¿Es posible realizar una acción personalizada cuando el usuario toca el enlace del teléfono detectado automáticamente en UITextView? Por favor, no aconseje usar UIWebView en su lugar.

Y por favor no solo repitan el texto de la referencia de las clases de Apple, ciertamente ya lo he leído.

Gracias.


Actualización: desde ios10 ,

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction;

Desde ios7 y posteriores, UITextView tiene el método de delegado:

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange *NS_DEPRECATED_IOS(7_0, 10_0, "Use textView:shouldInteractWithURL:inRange:forInteractionType: instead");*

para interceptar los clics a los enlaces. Y esta es la mejor manera de hacerlo.

Para ios6 y ios6 anteriores, una buena forma de hacerlo es UIApplication subclase UIApplication y sobrescribir el -(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

Deberá implementar openURL: en su delegado.

Ahora, para que la aplicación comience con su nueva subclase de UIApplication , ubique el archivo main.m en su proyecto. En este pequeño archivo que inicia su aplicación, generalmente hay esta línea:

int retVal = UIApplicationMain(argc, argv, nil, nil);

El tercer parámetro es el nombre de clase para su aplicación. Entonces, reemplazando esta línea por:

int retVal = UIApplicationMain(argc, argv, @"MyApplication", nil);

Esto hizo el truco para mí.


Con Swift 3 y i0S 10, la forma más sencilla de interactuar con números de teléfono, direcciones URL o direcciones en UITextView es usar UIDataDetectorTypes . El siguiente código muestra cómo mostrar un número de teléfono en una UITextView para que el usuario pueda interactuar con él.

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] } }

Con este código, al hacer clic en el número de teléfono, UIAlertController un UIAlertController .

Como alternativa, puede usar 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 } }

Con este código, al hacer clic en la cadena atribuida, UIAlertController un UIAlertController .

Sin embargo, es posible que desee realizar alguna acción personalizada en lugar de hacer UIAlertController un UIAlertController al hacer clic en un número de teléfono. O quizás desee mantener un UIAlertController para que aparezca y realice su propia acción personalizada al mismo tiempo.

En ambos casos, deberá hacer que su UIViewController ajuste al protocolo UITextViewDelegate e implementar textView(_:shouldInteractWith:in:interaction:) . El siguiente código muestra cómo hacerlo.

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 } }

Con este código, al hacer clic en el número de teléfono, no UIAlertController ningún UIAlertController y en su lugar obtendrá la siguiente impresión en su consola:

tel: +33687654321


En iOS 7 o posterior

Puede usar el siguiente método Delegado UITextView:

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange

La vista de texto llama a este método si el usuario pulsa o presiona prolongadamente el enlace URL. La implementación de este método es opcional. De forma predeterminada, la vista de texto abre la aplicación responsable de manejar el tipo de URL y le pasa la URL. Puede utilizar este método para activar una acción alternativa, como mostrar el contenido web en la URL en una vista web dentro de la aplicación actual.

Importante:

Los enlaces en vistas de texto son interactivos solo si la vista de texto es seleccionable pero no editable. Es decir, si el valor de UITextView la propiedad seleccionable es SÍ y la propiedad isEditable es NO.


No estoy seguro de cómo interceptaría el enlace de datos detectado o qué tipo de función necesita ejecutar. Pero es posible que pueda utilizar el método didBeginEditing TextField para ejecutar una prueba / exploración a través del campo de texto si sabe lo que está buscando ... como comparar cadenas de texto que cumplen con el formato ### - ### - ####, o comience con "www." para tomar esos campos, pero necesitaría escribir un pequeño código para oler a través de la cadena de campos de texto, reconocer lo que necesita y luego extraerlo para el uso de su función. No creo que esto sea tan difícil, una vez que haya definido exactamente qué es lo que quería y luego haya enfocado sus declaraciones if () hacia un patrón de coincidencia muy específico de lo que necesita.

Por supuesto, esto implica que el usuario va a tocar el cuadro de texto para activar el didBeginEditing (). Si ese no es el tipo de interacción con el usuario que buscaba, podría usar un temporizador de activación, que se inicia en ViewDidAppear () u otro según la necesidad y se ejecuta en la cadena de campos de texto, luego al final de ejecutar la cadena de campos de texto métodos que construiste, simplemente apaga el temporizador.


No lo he intentado yo mismo, pero puedes intentar implementar la application:handleOpenURL: método en tu aplicación delegada: parece que todas openURL solicitudes de openURL pasan por esta devolución de llamada.


Para 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 } }

o si el objetivo es> = IOS 10

func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool


Swift 4:

1) Cree la siguiente clase (UITextView subclasificado):

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) Dondequiera que configure su vista de texto, haga esto:

//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 está utilizando el guión gráfico, asegúrese de que su vista de texto se vea así en el inspector de identidad del panel derecho:



Voila! Ahora obtienes el enlace tocar inmediatamente en lugar de cuando la URL debe interactuar con el método URL


Tengo contenido dinámico en la vista de texto, que puede contener un enlace. El shouldInteractWithURL se llama solo cuando el usuario hace una presión prolongada en el enlace pero no realiza una llamada al tocar el enlace. Por favor redirija si algún amigo tiene referencia.

Lo siguiente es algo del código disparado.

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; }

El método de delegado anterior no se llama al tocar.

Saludos, Rohit Jankar


Versión Swift:

Su configuración estándar de UITextView debería verse más o menos así, no olvide delegar y dataDetectorTypes.

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)

Después de que termine su clase, agregue esta pieza:

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 } }


application:handleOpenURL: se application:handleOpenURL: cuando otra aplicación abre su aplicación abriendo una URL con un esquema compatible con su aplicación. No se llama cuando su aplicación comienza a abrir una URL.

Creo que la única forma de hacer lo que Vladimir quiere es usar un UIWebView en lugar de un UITextView. Haga que su controlador de vista implemente UIWebViewDelegate, configure el delegado de UIWebView en el controlador de vista y en el controlador de vista implemente webView:shouldStartLoadWithRequest:navigationType: para abrir [request URL] en una vista en lugar de salir de su aplicación y abrirla en Mobile Safari.