iPhone SDK - 在UITextView中打开链接到Web视图。

3

我已经在UITextView上指定了dataDetectorTypes,以便当用户点击URL时在Safari中打开。

是否有可能拦截此行为,以便我可以在UIWebView中加载URL?还是我需要编写自己的URL检测器代码来重新路由?

6个回答

3

在用户点击URL时,您需要进行URL检测并手动加载UIWebView。

由于苹果会将所有的http://https:// URL打开Safari,所以一切都需要定制化处理。


2
最好的解决方法是替换[UIApplication openURL:]方法的实现。
另一种方法是通过子类化UIApplication来实现,而不使用runtime.h。然后,重写openURL:选择器。使用这种方法,您可以从子类中调用[super openURL:]以获取您想要的默认处理的URL。对我来说,这种方法似乎更加清晰,因为您不需要干扰类的内部方法实现。
如果您选择这种方法,则还有两个重要的步骤。在main.m文件中,您需要更改UIApplicationMain函数调用的第三个参数,以使其与您的子类名称匹配:
int retVal = UIApplicationMain(argc, argv, @"MyApplicationSubclass", nil);

此外,您应该将MainWindow.xib文件中的File's Owner类从UIApplication更改为您的子类。

这对于那些想要在整个应用程序中拥有自己的实现的人来说非常完美。我发现它非常有用。 - Nareshkumar

1

我为大家做了一件好事,用博客文章和演示应用程序回答了你的问题。

http://52apps.net/post/879106231/method-swizzling-uitextview-and-safari http://github.com/marksands/UITextViewLinkOptions

为了进一步解释tt.Kilew的帖子,您可以创建类别,但将方法命名为其他名称,例如customOpenURL。当您想返回Safari时,您需要进行一种称为方法交换的操作。代码如下:

#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时,只需调用此方法以交换openURL实现和customOpenURL实现。

查看演示应用程序以获取更多详细信息。希望这可以帮助你! :)

编辑

如果您不想冒险被拒绝,您可能需要查看我开发的自定义UITextView以更好地适应情况:https://github.com/marksands/MSTextView


很好 - 不知道最近是否有任何变化,但是有人的应用程序使用Three20框架被拒绝了方法交换(我相信Three20已更新为不再使用它)。http://groups.google.com/group/three20/browse_thread/thread/ea606b4114565e75 - Shazron
你说得对!我开始实现一个自定义的UITextView来更好地处理URL。这种方法效果更好,不会被苹果拒绝。你可以在这里查看项目https://github.com/marksands/MSTextView - Mark Sands

0

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
    }
}

0

另一个答案 :) 对我来说有效的方法是重新实现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];
}

我找到了这个链接,它会展示给你MyWatcher是什么 - 我在寻找答案时偶然发现的 - https://github.com/marksands/UITextViewLinkOptions/blob/master/Classes/UITextViewLinkOptionsAppDelegate.m#L14-22 - jwknz
如果我这样做,苹果会拒绝我的应用程序吗?令我担心的是“Private”。它在这里有什么作用呢? - Sufian
你可以随意命名类别。openURL根本不是私有方法。另一个选项是使用自己的实现子类化UIApplication,并使用方法覆盖而不是类别。 - tt.Kilew

-2
你可以尝试在你的应用程序代理中实现application:handleOpenURL:方法。每当一个URL被打开时,这个方法都会被调用。在这里,你应该能够让URL在你的Web视图中打开。

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