如何拦截点击UITextView中的链接?

当用户在UITextView中触摸自动检测的手机链接时,是否可以执行自定义操作。 请不要建议使用UIWebView。

请不要只重复苹果课程中的文字参考 – 当然我已经读过了。

谢谢。

更新:从ios10 ,

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

从ios7和更高版本开始, UITextView具有委托方法:

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

拦截点击链接。 这是最好的方法。

对于ios6和更早版本,一个很好的方法是通过inheritance UIApplication并覆盖-(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 

您需要在委托中实现openURL:

现在,要让应用程序从UIApplication的新子类开始,请在项目中找到main.m文件。 在这个引导你的应用程序的小文件中,通常有这一行:

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

第三个参数是应用程序的类名。 所以,将此行替换为:

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

这对我有用。

在iOS 7或更高版本中

您可以使用以下UITextView委托方法:

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

如果用户点击或长按URL链接,则文本视图会调用此方法。 此方法的实现是可选的。 默认情况下,文本视图会打开负责处理URL类型的应用程序并将URL传递给它。 您可以使用此方法触发替代操作,例如在当前应用程序的Web视图中的URL处显示Web内容。

重要:

仅当文本视图可选但不可编辑时,文本视图中的链接才是交互式的。 也就是说,如果UITextView的值为selectable属性为YES且isEditable属性为NO。

Swift版本:

您的标准UITextView设置应该如下所示,不要忘记委托和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) 

课程结束后添加这篇文章:

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

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

或者如果目标是> = IOS 10

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

使用Swift 3和i0S 10,与UITextView电话号码,url或地址进行交互的最简单方法是使用UIDataDetectorTypes 。 下面的代码显示了如何在UITextView显示电话号码,以便用户可以与之交互。

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

使用此代码,当单击电话号码时,将弹出UIAlertController


作为替代方案,您可以使用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 } } 

使用此代码,当单击属性字符串时,将弹出UIAlertController


但是,您可能需要执行一些自定义操作,而不是在单击电话号码时弹出UIAlertController 。 或者您可能希望保持UIAlertController弹出并同时执行您自己的自定义操作。

在这两种情况下,您都必须使UIViewController符合UITextViewDelegate协议并实现textView(_:shouldInteractWith:in:interaction:) 。 下面的代码显示了如何执行此操作。

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

使用此代码,当单击电话号码时,将不会弹出UIAlertController ,您将在控制台中获得以下打印:

联系电话:33687654321

我在文本视图中有动态内容,可能包含链接。 只有当用户长按链接但未点击链接时,才会调用shouldInteractWithURL。 如果有任何好友参考,请重定向。

以下是一些狙击的代码。

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

上面的委托方法没有被点击调用。

此致,Rohit Jankar

斯威夫特4:

1)创建以下类(子类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)无论您在何处设置文本视图,请执行以下操作:

 //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") } } 

如果您使用的是故事板,请确保右侧窗格标识检查器中的textview看起来像这样:
在此处输入图像描述

瞧! 现在,您可以立即获取链接,而不是URL shouldInteractWith URL方法

我自己没有尝试过,但你可以尝试在应用程序委托中实现application:handleOpenURL:方法 – 看起来所有openURL请求都通过此回调。

不确定如何拦截检测到的数据链接,或者您需要运行什么类型的function。 但是,如果您知道要查找的内容,则可以使用didBeginEditing TextField方法在文本字段中运行测试/扫描。例如,比较符合### – ### – #### format的文本字符串,或者以“www。”开头。 抓住那些字段,但你需要编写一些代码来嗅探文本域字符串,重新调整你需要的东西,然后提取它以供你的函数使用。 一旦你缩小了你想要的内容,然后将你的if()语句过滤到你所需要的非常具体的匹配模式,我认为这不会那么困难。

这意味着用户将触摸文本框以激活didBeginEditing()。 如果那不是您正在寻找的用户交互类型,您可以使用触发器Timer,它根据需要从ViewDidAppear()或其他开始,并运行textfields字符串,然后在您运行textfield字符串的末尾您构建的方法,只需关闭Timer即可。

application:handleOpenURL:当另一个应用程序通过打开您的应用程序支持的方案的URL打开您的应用程序时调用。 当您的应用开始打开url时,系统不会调用它。

我认为做Vladimir想要的唯一方法是使用UIWebView而不是UITextView。 使视图控制器实现UIWebViewDelegate,将UIWebView的委托设置为视图控制器,并在视图控制器中实现webView:shouldStartLoadWithRequest:navigationType:在视图中打开[request URL] ,而不是退出应用程序并在Mobile Safari中打开它。