Como interceptar clique no link no UITextView?
-
23-09-2019 - |
Pergunta
É possível executar uma ação personalizada quando o usuário toca no link do telefone detectado automaticamente no UITextView.Por favor, não aconselhe usar o UIWebView.
E, por favor, não repita apenas o texto da Apple Classes Reference - certamente eu já o li.
Obrigado.
Solução
ATUALIZAÇÃO: De iOS10,
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction;
A partir de iOS7 e depois UITextView
tem o método 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 os cliques nos links. E esta é a melhor maneira de fazer isso.
Por iOS6 e mais cedo uma boa maneira de fazer isso é a subclasse UIApplication
e substituindo o -(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
Você precisará implementar openURL:
em seu delegado.
Agora, para que o aplicativo comece com sua nova subclasse de UIApplication
, localize o arquivo main.m em seu projeto. Neste pequeno arquivo que inicializa seu aplicativo, geralmente há esta linha:
int retVal = UIApplicationMain(argc, argv, nil, nil);
O terceiro parâmetro é o nome da classe para o seu aplicativo. Então, substituindo esta linha para:
int retVal = UIApplicationMain(argc, argv, @"MyApplication", nil);
Isso fez o truque para mim.
Outras dicas
No iOS 7 ou mais tarde
Você pode usar o seguinte método uitextview delegado:
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
A visualização de texto chama esse método se o usuário tocar ou pressionar há muito tempo o link URL. A implementação deste método é opcional. Por padrão, a exibição de texto abre o aplicativo responsável pelo manuseio do tipo URL e passa pelo URL. Você pode usar esse método para acionar uma ação alternativa, como exibir o conteúdo da Web na URL em uma visualização da Web no aplicativo atual.
Importante:
Os links nas visualizações de texto são interativos apenas se a visualização de texto for selecionável, mas não editável. Ou seja, se o valor do UITEXTVIEW, a propriedade selecionável for sim e a propriedade isedável for não.
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
}
}
ou se o destino é> = iOS 10
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool
Adicionando JavaScript a um conteúdo da página Wiki é o mesmo que adicioná-lo a um CEWP.O resultado final é que o SharePoint retira o código e converterá hiperlinks com javascript para tags inúteis, conforme mostrou.
A única solução, que pelo caminho também é uma prática recomenda, é adicionar um CEWP * à sua página e vincular um arquivo JavaScript externo (que você terá upload para uma biblioteca do Doc em seu site) no conteúdo) no conteúdo) no conteúdocaixa de link.
[*] como alternativa à solução comumente proposta de utilização de um CEP, você pode fazer uso da Web Part HTML, que permite colocar o código JavaScript dentro dele, sem incorrer emseu código sendo despojado.
Com o Swift 5 e o iOS 12, você pode usar um dos três padrões seguintes para interagir com links em um UITextView
.
#1. Usando UITextView
's dataDetectorTypes
propriedade.
A maneira mais simples de interagir com números de telefone, URLs ou endereços em um UITextView
é usar dataDetectorTypes
propriedade. O código de exemplo abaixo mostra como implementá -lo. Com este código, quando o usuário toca no número de telefone, um UIAlertController
aparece.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let textView = UITextView()
textView.text = "Phone number: +33687654321"
textView.isUserInteractionEnabled = true
textView.isEditable = false
textView.isSelectable = true
textView.dataDetectorTypes = [.phoneNumber]
textView.isScrollEnabled = false
textView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(textView)
textView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
textView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
textView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor).isActive = true
}
}
#2. Usando UITextViewDelegate
's textView(_:shouldInteractWith:in:interaction:)
método
Se você deseja realizar alguma ação personalizada em vez de fazer um UIAlertController
apareça quando você toca em um número de telefone enquanto usa dataDetectorTypes
, você tem que fazer o seu UIViewController
de acordo com UITextViewDelegate
protocolo e implementação textView(_:shouldInteractWith:in:interaction:)
. O código abaixo mostra como implementá -lo:
import UIKit
class ViewController: UIViewController, UITextViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let textView = UITextView()
textView.delegate = self
textView.text = "Phone number: +33687654321"
textView.isUserInteractionEnabled = true
textView.isEditable = false
textView.isSelectable = true
textView.dataDetectorTypes = [.phoneNumber]
textView.isScrollEnabled = false
textView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(textView)
textView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
textView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
textView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor).isActive = true
}
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
/* perform your own custom actions here */
print(URL) // prints: "tel:+33687654321"
return false // return true if you also want UIAlertController to pop up
}
}
#3. Usando NSAttributedString
e NSAttributedString.Key.link
Como alternativa, você pode usar NSAttributedString
e definir a URL
para o seu NSAttributedString.Key.link
atributo. O código de amostra abaixo mostra uma possível implementação dele. Com este código, quando o usuário toca na sequência atribuída, um UIAlertController
aparece.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let attributedString = NSMutableAttributedString(string: "Contact: ")
let phoneUrl = NSURL(string: "tel:+33687654321")! // "telprompt://+33687654321" also works
let attributes = [NSAttributedString.Key.link: phoneUrl]
let phoneAttributedString = NSAttributedString(string: "phone number", attributes: attributes)
attributedString.append(phoneAttributedString)
let textView = UITextView()
textView.attributedText = attributedString
textView.isUserInteractionEnabled = true
textView.isEditable = false
textView.isSelectable = true
textView.isScrollEnabled = false
textView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(textView)
textView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
textView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
textView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor).isActive = true
}
}
Você poderia resolver isso com código, mas estou assumindo que você quer uma solução fora da caixa.Terá que haver comprometimentos ...
Eu acho que o problema com sua abordagem é que você está apenas verificando se o evento está ou não aberto ou não o usuário está no formulário de inscrição.Uma abordagem diferente pode ser:
lista de eventos contém lista de eventos
Cada evento tem sua própria lista associada segurando usuários registrados
lista de eventos tem uma coluna calculada que contém uma fórmula.A fórmula irá analisar o campo de status, se o status estiver aberto, a coluna calculada retornará um URL.Se o status estiver fechado, a fórmula não retornará nada, ou uma mensagem dizendo que o registro está fechado.
Para que isso funcione suas listas precisará de uma convenção de nomenclatura consistente para que a fórmula gere consistentemente um URL válido.
tal
Não tenho certeza de como você interceptaria o link de dados detectado ou que tipo de função você precisa executar.Mas você poderá utilizar o método DidBeginEditing Textfield para executar um teste/digitalizar através do campo de texto, se você souber o que está procurando ... como comparando seqüências de texto que se encontram ###-###-#### Format, Ou comece com "www". Para pegar esses campos, mas você precisaria escrever um pequeno código para farejar através da string textfields, reconizar o que precisa e extraí -lo para uso da sua função.Não acho que isso seria tão difícil, uma vez que você restringiu exatamente o que queria e, em seguida, concentrou seus filtros de instrução if() em um padrão de correspondência muito específico do que você precisava.
Claro que isso implica que o usuário irá tocar na caixa de texto para ativar o didBeginEditing().Se esse não for o tipo de interação do usuário que você estava procurando, você pode simplesmente usar um temporizador de gatilho, que começa em ViewDidAppear() ou outro com base na necessidade e percorre a string de campos de texto e, no final, você executa a string de campos de texto métodos que você construiu, basta desligar o temporizador.
application:handleOpenURL:
é chamado quando outro aplicativo abre sua Aplicativo abrindo um URL com um esquema que seu aplicativo suporta. Não é chamado quando seu aplicativo começa a abrir um URL.
Eu acho que a única maneira de fazer o que o Vladimir quer é usar um UIWebView em vez de um UITEXTVIEW. Faça do seu controlador de exibição implementar UIWebViewDelegate, defina o delegado do UIWebView para o controlador de exibição e no implemento do View Controller webView:shouldStartLoadWithRequest:navigationType:
abrir [request URL]
Em uma visão, em vez de desistir do seu aplicativo e abri -lo no Mobile Safari.
Swift 4:
1) Crie a aula a seguir (subclassem uitextview):
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) Onde quer que você configure seu TextView, faça isso:
//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")
}
}
Se você estiver usando o storyboard, verifique se sua visão de texto se parece com isso no inspetor de identidade do painel certo:
Pronto! Agora você obtém o link Tap imediatamente em vez de quando o URL deve interromper o método URL