如何在UIWebView中打开UITextView中的网页链接而不是Safari?

15

我正在开发一款 iPhone 3.0 应用程序。我试图将 UITextView 中的网页链接在 UIWebView 中打开,而不是 Safari。但还是没成功。

UITextView 不可编辑,它能够很好地检测到网页链接并在 Safari 中打开。

如何避免这种情况?如何获取该 URL,以便我可以在自己的 UIWebView 中使用?

3个回答

22

这是一个旧问题,但如果有人正在寻找更新的方法,请参考以下步骤:

在视图控制器(viewController)的.m文件中将包含UITextView的viewController指定为代理,并添加以下代码:

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

    //Do something with the URL
    NSLog(@"%@", URL);


    return NO;
}

我相信这是 iOS 7 的正确方式。这对我很有帮助,所以谢谢你! - ajfigueroa
@nihad 非常感谢,这个方案看起来比旧方案更简洁、更易于操作。 - sunny

8
在Swift 3中,UITextViewDelegate提供了一个textView(_:shouldInteractWith:in:interaction:)方法。其声明如下:

询问代理是否允许指定文本视图在给定的文本范围内使用指定类型的URL进行用户交互。

该方法用于判断文本视图是否应该允许用户与给定的URL进行交互,并要求代理返回一个布尔值作为判断依据。
optional func textView(_ textView: UITextView,  shouldInteractWith URL: URL,  in characterRange: NSRange,  interaction: UITextItemInteraction) -> Bool

以下代码展示了如何在SFSafariViewController中打开UITextView的网页链接,而不是在Safari应用程序中打开它们:
import UIKit
import SafariServices

class ViewController: UIViewController, UITextViewDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Set textView
        let textView = UITextView()
        textView.text = "http://www.yahoo.fr http://www.google.fr"
        textView.isUserInteractionEnabled = true
        textView.isEditable = false
        textView.isSelectable = true
        textView.dataDetectorTypes = UIDataDetectorTypes.link

        // Add view controller as the textView's delegate
        textView.delegate = self

        // auto layout
        view.addSubview(textView)
        textView.translatesAutoresizingMaskIntoConstraints = false
        textView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        textView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        textView.heightAnchor.constraint(equalToConstant: 300).isActive = true
        textView.widthAnchor.constraint(equalToConstant: 300).isActive = true
    }

    func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
        // Open links with a SFSafariViewController instance and return false to prevent the system to open Safari app
        let safariViewController = SFSafariViewController(url: URL)
        present(safariViewController, animated: true, completion: nil)

        return false
    }

}

7

最简单的方法是覆盖UITextView上的webView:decidePolicyForNavigationAction:request:frame:decisionListener:方法,如下所示:

@interface UITextView (Override)
@end

@class WebView, WebFrame;
@protocol WebPolicyDecisionListener;

@implementation UITextView (Override)

- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id < WebPolicyDecisionListener >)listener
{
    NSLog(@"request: %@", request);
}
@end

这将影响应用程序中的所有UITextView。如果您只需要在单个视图上执行此操作,请创建子类并覆盖该方法。

注意:这实际上是一个私有API,随时可能被删除。没有办法通过公共API来执行此操作。

编辑:从iOS 7.0开始,在UITextViewDelegate上引入了一个新方法来支持此操作。有关详细信息,请参见nihad的答案。


1
嗯,作为私有的应用,你认为这会对App Store的批准造成问题吗?顺便说一下,今晚我会检查你的代码并告诉你。谢谢。 - lucadb
这不是他们可以检查的类型,但您可能会在未来的操作系统更改中稍微有些风险(这是桌面版中的公共API,而且苹果很可能不会停止使用WebKit,但这是可能的)。最糟糕的情况是行为会返回到启动MobileSafari的默认设置。 - rpetrich
1
我不会冒险尝试。我不确定子类化UIApplication并覆盖openURL:是否被视为私有的;它可能是,但比我的答案更接近公共API。 - rpetrich
我从未使用这段代码提交过应用程序。我完全同意@rpetrich和@Roger Nolan的观点。 - lucadb
@rpetrich 能否有人澄清一下我应该把上面的代码放在哪里?我已经开发了大约6个月的应用程序,但我仍然对文件结构和任何与扩展基类相关的内容感到困惑。我应该把这段代码放在哪里,需要什么样的文件名?如果不是子类化UITextView,我知道如何做,但是这段代码应该放在哪里? - sunny
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接