【发布时间】:2009-12-11 16:41:01
【问题描述】:
我在 UITextView 上指定了 dataDetectorTypes,以便在触摸时在 Safari 中打开 URL。
是否可以拦截此行为,以便我将 URL 加载到 UIWebView 中?或者我会编写自己的 URL 检测器代码来重新路由它吗?
【问题讨论】:
标签: iphone uiwebview uitextview datadetectortypes
我在 UITextView 上指定了 dataDetectorTypes,以便在触摸时在 Safari 中打开 URL。
是否可以拦截此行为,以便我将 URL 加载到 UIWebView 中?或者我会编写自己的 URL 检测器代码来重新路由它吗?
【问题讨论】:
标签: iphone uiwebview uitextview datadetectortypes
您必须自己进行 URL 检测并在点击 URL 时手动加载 UIWebView。
一切都需要定制,因为 Apple 会将所有 http:// 和 https:// URL 开口发送到 Safari。
【讨论】:
上面最有效的答案是替换 [UIApplication openURL:] 的方法实现
另一种不使用 runtime.h 的方法是继承 UIApplication。然后,覆盖 openURL: 选择器。使用这种方法,您可以从您的子类中调用 [super openURL:] 来获取您想要默认处理的 URL。它对我来说似乎也更干净一些,因为您不需要弄乱类的内部方法实现。
不过,如果您选择这种方法,还有 2 个其他重要步骤。在 main.m 文件中,您需要更改 UIApplicationMain 函数调用的第三个参数,使其与您的子类的名称匹配:
int retVal = UIApplicationMain(argc, argv, @"MyApplicationSubclass", nil);
另外,您可能应该将 MainWindow.xib 文件中文件所有者的类从 UIApplication 更改为您的子类。
【讨论】:
我帮了大家一个忙,并通过博客文章和演示应用回答了您的问题。
http://52apps.net/post/879106231/method-swizzling-uitextview-and-safari
http://github.com/marksands/UITextViewLinkOptions
要扩展 tt.Kilew 的帖子,您可以创建类别,但将您的方法称为其他名称,例如 customOpenURL。当你想回到 Safari 时,你会做一些叫做 Method Swizzling 的事情。它看起来像这样:
#import <objc/runtime.h>
..
Method customOpenUrl = class_getInstanceMethod([UIApplication class], @selector(customOpenURL:));
Method openUrl = class_getInstanceMethod([UIApplication class], @selector(openURL:));
method_exchangeImplementations(customOpenUrl, openUrl);
当您想使用 Safari 或不想使用 Safari 时,只需调用此方法即可将 openURL 实现与您的 customOpenURL 实现交换。
查看demo app 了解更多详情。希望这可以帮助! :)
如果您不想冒应用被拒绝的风险,您可能需要查看我开发的自定义 UITextView 以更好地适应这种情况:https://github.com/marksands/MSTextView
【讨论】:
另一个答案 :) 对我来说很好的是重新实现 UIApplication openURL:(NSURL *) url
@interface UIApplication (Private)
- (BOOL)openURL:(NSURL*)url;
@end
@implementation UIApplication (Private)
- (BOOL)openURL:(NSURL*)url {
// all viewcontrollers should change currentViewController to self
if ([MyWatcher currentViewController]) {
// Do anything you want
[[MyWatcher handleURL:url withController:[MyWatcher currentViewController]];
return YES;
}
return NO;
}
@end
... Some view controller
- (void)viewDidLoad {
[super viewDidLoad];
[MyWatcher setCurrentController:self];
}
【讨论】:
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)
在您的课程结束后添加以下内容: 请注意,您需要 https://github.com/TransitApp/SVWebViewController 这个库,据我所知,这是目前最好的。
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
}
}
【讨论】:
您可以尝试在您的应用程序委托中实现application:handleOpenURL:。
每当打开 url 时都应该调用此方法。在这里,您应该能够在您的 webview 中打开 URL。
【讨论】: