代码之家  ›  专栏  ›  技术社区  ›  Vladimir

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

  •  89
  • Vladimir  · 技术社区  · 16 年前

    当用户在uitextview中触摸自动检测到的电话链接时,是否可以执行自定义操作。请不要建议改用uiwebview。

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

    谢谢。

    9 回复  |  直到 8 年前
        1
  •  130
  •   Aleksander Azizi VikashVikash SinghSingh    8 年前

    更新:来自 ,

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

    以后 UITextView 具有委托方法:

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

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

    为了 早些时候,一个很好的方法是通过子类化 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);
    

    这对我有好处。

        2
  •  50
  •   Rajan Balana    12 年前

    在iOS 7或更高版本中

    可以使用以下uitextView委托方法:

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

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

    重要:

    文本视图中的链接只有在文本视图为 可选择但不可编辑。也就是说,如果uitextview的值 selectable属性是yes,iseditable属性是no。

        3
  •  5
  •   Ryan Heitner    9 年前

    斯威夫特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
    
        4
  •  4
  •   Esqarrouth Jeremias Binder    11 年前

    SWIFT版本:

    您的标准uitextview设置应该如下所示,不要忘记委托和datadetectorypes。

    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
        }
    }
    
        5
  •  2
  •   Imanou Petit    9 年前

    使用swift 3和i0s 10,与 UITextView 是使用 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
        }
    
    }
    

    使用此代码,当单击属性字符串时, uialert控制器 将弹出。


    但是,您可能希望执行一些自定义操作,而不是 uialert控制器 单击电话号码时弹出。或者你可能想保留一个 uialert控制器 同时弹出并执行您自己的自定义操作。

    在这两种情况下,你必须 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
        }
    
    }
    

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

    电话:+33687654321

        6
  •  0
  •   Vladimir    16 年前

    我自己也没试过但你可以试着去实现 application:handleOpenURL: 方法-它看起来像 openURL 请求通过此回调传递。

        7
  •  0
  •   Newbyman    16 年前

    不确定如何截获检测到的数据链路,或者需要运行什么类型的函数。但是,如果您知道自己要查找的是什么,则可以使用didbeginediting textfield方法对textfield运行测试/扫描..例如比较满足格式的文本字符串,或者从“www”开始获取这些字段,但是您需要编写一些代码来嗅探通过textfields字符串,重新确定需要的内容,然后提取出来供函数使用。我不认为这会有那么困难,一旦你缩小了你想要的范围,然后集中你的if()语句过滤器到你需要的非常具体的匹配模式。

    当然,这意味着用户将触摸文本框以激活didbeginediting()。如果这不是您正在寻找的用户交互类型,您可以只使用触发器计时器,它根据需要在viewDidAppear()或其他上启动并运行textFields字符串,然后在运行完您构建的textField字符串方法后,只需转动计时器退后。

        8
  •  0
  •   A. Jesse Jiryu Davis    16 年前

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

    我认为弗拉基米尔想要的唯一方法是使用uiwebview而不是uitextview。使视图控制器实现uiwebview delegate,将uiwebview的委托设置为视图控制器,并在视图控制器实现中 webView:shouldStartLoadWithRequest:navigationType: 打开 [request URL] 而不是退出应用程序并在Mobile Safari中打开它。

        9
  •  0
  •   Josh O'Connor    8 年前

    斯威夫特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")
        }
    }
    


    如果您正在使用序列图像板,请确保您的文本视图在右窗格标识检查器中如下所示:
    enter image description here



    哇!现在,您可以立即获得link tap,而不是url应该interactwith url方法