如何拦截点击UITextView中的链接?
当用户在UITextView中触摸自动检测到的手机链接时是否可以执行自定义操作? 请不要build议使用UIWebView。
请不要只重复苹果类的参考文本 – 当然我已经读过了。
谢谢。
更新:从iOS 7和更高版本UITextView具有委托方法:
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
拦截点击链接。 这是最好的办法。
对于iOS 6和更早的版本,一个很好的方法是通过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
的新子类开始,请在您的项目中find文件main.m。 在这个引导你的应用程序的小文件中,通常有这样一行:
int retVal = UIApplicationMain(argc, argv, nil, nil);
第三个参数是您的应用程序的类名称。 所以,replace这条线为:
int retVal = UIApplicationMain(argc, argv, @"MyApplication", nil);
这为我做了诡计。
在iOS 7或更高版本中
您可以使用下面的UITextView委托方法:
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
如果用户点击或长按URL链接,则文本视图会调用此方法。 这个方法的实现是可选的。 默认情况下,文本视图将打开负责处理URLtypes的应用程序并将其传递给URL。 您可以使用此方法触发替代操作,例如在当前应用程序的Web视图的URL中显示Web内容。
重要:
文本视图中的链接只有在文本视图可选但不可编辑的情况下才是交互式的。 也就是说,如果UITextView的可选属性的值是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] } }
用这个代码,当点击电话号码时,会popup一个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 } }
用这个代码,当点击属性string时,会popup一个UIAlertController
。
但是,您可能需要执行一些自定义操作,而不是在单击电话号码时popupUIAlertController
。 或者你可能想保持一个UIAlertController
popup,并在同一时间执行自己的自定义操作。
在这两种情况下,您将不得不使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 } }
有了这个代码,当点击电话号码时,将不会popupUIAlertController
,而是在控制台中获得以下打印内容:
联系电话:33687654321
我在文本视图中有可能包含链接的dynamic内容。 shouldInteractWithURL只有在用户长按链接时才会被调用,而不是链接的调用。 如果有任何好友参考,请redirect。
以下是一些sniped的代码。
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
我还没有尝试过,但你可以尝试在应用程序委托中实现application:handleOpenURL:
方法 – 它看起来像所有的openURL
请求通过这个callback。
不知道如何拦截检测到的数据链接,或者需要运行哪种types的function。 但是如果你知道你在找什么东西的话,你可以利用didBeginEditing TextField方法在文本框中运行一个testing/扫描。比如符合### – ### – ####格式的文本string,或者以“www”开头。 来抓取这些字段,但是您需要编写一些代码来嗅探textfieldsstring,重新调整您需要的内容,然后将其解压缩以供函数使用。 我不认为这会很难,一旦你精确地缩小了你想要的,然后把你的if()语句filter集中到你需要的非常特定的匹配模式。
这意味着用户将触摸文本框以激活didBeginEditing()。 如果这不是您所寻找的用户交互types,那么您可以使用一个触发器Timer,它根据需要在ViewDidAppear()或其他开始的位置启动,并在textfieldsstring中运行,然后在运行完文本string你build立的方法,你只需closures定时器。
application:handleOpenURL:
当另一个应用程序通过打开您的应用程序支持的scheme打开您的应用程序时被调用。 当您的应用程序开始打开一个URL时,它不会被调用。
我认为做弗拉基米尔想要的唯一方法是使用UIWebView而不是UITextView。 使您的视图控制器实现UIWebViewDelegate,将UIWebView的委托设置到视图控制器,并在视图控制器中实现webView:shouldStartLoadWithRequest:navigationType:
在视图中打开[request URL]
,而不是退出您的应用程序,并在Mobile Safari中打开它。