如何拦截点击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中打开它。