从UITextView自动检测链接

时间:2015-10-08 03:31:01

标签: ios objective-c uiviewcontroller mobile-safari

我有UIViewController UITextView,可以自动检测文本中的超链接。它工作正常,但我会使用SFSafariViewController来打开链接,这样我就可以“留在”我的应用程序中,而不是打开一个单独的浏览器,这是“开箱即用”的行为。

我已经采取了下面的步骤,但网站仍然打开一个单独的Safari浏览器,而不是在我的应用程序内。我没有收到任何错误或警告,但检测到的网站仍在单独的浏览器中打开,而不是在我的应用程序中。 UITextViewDelegate方法似乎没有被调用(我将一个日志语句放入检查中)。

我查看UITextViewDelegate,我想我想使用此方法打开UITextView检测到的网站:

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange {
    // Fill code in here to use SFSafariViewController
    return YES;
}

到目前为止我做了什么:

1)导入SafariServices,制作委托声明,并在MyViewController中声明委托属性。 h

@import SafariServices;

@interface MyViewController : UIViewController <UITextViewDelegate, SFSafariViewControllerDelegate>

@property(nonatomic, weak, nullable) id< SFSafariViewControllerDelegate, SFSafariViewControllerDelegate > delegate;

2)在我的.m文件中添加了一个委托部分,并尝试从上面的存根中填写此方法:

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange {
    SFSafariViewController *websiteToOpen = [[SFSafariViewController alloc]initWithURL:URL entersReaderIfAvailable:YES];
    websiteToOpen.delegate = self;
    [self presentViewController:websiteToOpen animated:YES completion:nil];
    return YES;
}

我确信这是100%我把它弄糟,但我无法超越终点线。我错过了什么?

3 个答案:

答案 0 :(得分:7)

如果有人正在寻找 Swift 3 实施。

有效的解决方案:

1.导入Safari服务

import SafariServices

2.创建属性文本,添加链接,将字符串分配给textView

let myLink = "google.com"
let myText = "here is my link: \(myLink)"
let myAttributedText = NSMutableAttributedString(string: myText)
let rangeOfMyLink = myText.range(of: myLink)
if rangeOfMyLink.location != NSNotFound {
    myAttributedText.addAttributes([NSLinkAttributeName: myLink], range: rangeOfMyLink)
}
myTextView.attributedText = myAttributedText
myTextView.delegate = self

3.将代表添加到VC:

class MyViewController: UIViewController, UITextViewDelegate

4.添加委托方法:

func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
    let safariVC = SFSafariViewController(url: URL)
    present(safariVC, animated: true, completion: nil)
    return false
}

希望它有所帮助!

答案 1 :(得分:3)

您在实施结束时返回YES,告诉系统,继续执行您要对此URL执行的操作(在本例中为打开的Safari)。如果您决定自己处理此问题,请返回NO

话虽如此,但有几点需要注意:

  • Safari视图控制器仅支持http / https网址。确保在使用Safari视图控制器之前检查URL.scheme
  • 虽然textView:shouldInteractWithURL:inRange:的文档建议您应该使用此方法拦截网址上的点按...

      

    您可以使用此方法触发替代操作,例如在当前应用程序的Web视图中的URL处显示Web内容。

    ......你要小心。 “应该互动”不仅包括常规点击 - 这种方法也会被称为长按等等,这通常会有不同的行为,我无法确定为什么正在调用此委托方法。

出于这些原因,您可以考虑将自己的UITapGesturRecognizer附加到UITextView,详见this answer

答案 2 :(得分:1)

我正在尝试做同样的事情,但遇到了不同的问题。

首先,您需要设置文本视图的委托才能触发delegate方法。我在viewDidLoad中执行此操作:

myTextView.delegate = self;

然后,告诉您的UITextView 与网址互动:

- (BOOL)textView:(UITextView *)textView 
        shouldInteractWithURL:(NSURL *)url 
        inRange:(NSRange)characterRange
{
    [self presentViewController:websiteToOpen animated:YES completion:nil];
    return NO;
}

有了这个,我可以呈现safari视图控制器,虽然它是空的,即没有内容,也没有完成按钮。所以我做错了什么......