【问题标题】:Stop WebView from going to any urls阻止 WebView 访问任何 url
【发布时间】:2011-12-09 16:36:32
【问题描述】:

我为 mac 制作了一个简单的应用程序,但是当它加载内容(通过 JS)时,由于添加或其他原因,它会重定向,有没有办法阻止 WebView 转到任何其他 URL,而不是在代码?

目前正试图通过 (UPDATED) 来阻止它

webberAppDelegate.h

#import <Cocoa/Cocoa.h>
#import <WebKit/WebKit.h>
@interface webberAppDelegate : NSObject <NSApplicationDelegate> {
    WebView *webview;
}

@property (assign)IBOutlet WebView *webview;

@end

webberAppDelegate.m

#import "webberAppDelegate.h"

@implementation webberAppDelegate

//@synthesize window;
//@synthesize webber;
@synthesize webview;

- (void)applicationDidFinishLaunching:(NSNotification *)Notification 
{
    NSURL*url=[NSURL URLWithString:@"http://simplyshows.com/dev/forums/"];
    NSURLRequest*request=[NSURLRequest requestWithURL:url];
    [[webview mainFrame] loadRequest:request];
    webview.resourceLoadDelegate = self;

}

-(NSURLRequest*) webView:(WebView*)webview resource:(id)sender willSendRequest:(NSURLRequest*)request redirectResponse:(NSURLResponse*)redirectresponse fromDataSource:(WebDataSource*)dataSource {
    NSLog(@"willSendRequest delegate method called");
}

@end

【问题讨论】:

    标签: objective-c xcode macos uiwebview


    【解决方案1】:

    有关connection:willSendRequest:redirectResponse:的详细信息,请参阅here

    更新:抱歉,我对这是一个 Mac 应用程序而不是 iPhone 应用程序这一事实轻描淡写。对前者的经验有限;但是,我相信相同的概念适用,只是实例化方式不同。

    查看文档,您似乎想要webView:resource:willSendRequest:redirectResponse:fromDataSource(有关详细信息,请参阅here)。您还需要将webberAppDelegateresourceLoadDelegate 设置为self

    更新:好的,这里有更多关于这个过程的细节。你需要了解一下 protocolsdelegates 在 Objective-C 中是如何工作的。阅读该材料以支持以下内容。

    协议功能类似于 Java 或 C# 中的接口,或 C++ 中的抽象函数。它们基本上是一种合同形式。它们默认是强制性的,但可以显式标记为@optional,这意味着如果省略一个,编译器不会阻塞。如果您查看WebResourceLoadDelegate 的文档,您会发现所有方法都是可选的。我们只需要一个,webView:resource:willSendRequest:redirectResponse:fromDataSource 方法。

    另一部分是委托的概念。委托作为回调函数。这涉及将执行回调逻辑的对象和逻辑的实现(即,上述协议中的方法的实现)。这可以通过多种方式实现,但 Cocoa 有一种或多或少标准化的方式来实现它。您需要提供该方法的实现,并且您需要确定哪个对象将执行该逻辑。请注意,WebView 有一堆不同的委托协议。全部或部分采用其中之一称为符合协议。这在代码中表示为(我在这里提供了你的类的骨架):

    @interface webberAppDelegate : NSObject<WebResourceLoadDelegate> {
        WebView* webview;
    }
    @end
    

    这里我假设你来自NSObject;替换您的基类。这让编译器知道您将提供强制方法的实现以及您需要的任何可选方法。如果你不实现强制方法,它会报错。

    更关键的部分是确定Webview ivar 有一个委托,该委托将为WebResourceLoadDelegate 声明的一个或所有方法提供实现。你有这个 ivar 的属性——webview。在某个地方(例如,在 viewDidLoad 中——我会在 iOS 中这样做)你需要声明:

    webview.resourceLoadDelegate = self;
    

    假设您希望由webberAppDelegate 处理回调。那么在webberAppDelegate的实现中需要提供webView:resource:willSendRequest:redirectResponse:fromDataSource方法的定义:

    -(NSURLRequest*) webView:(WebView*)webview resource:(id)sender willSendRequest:(NSURLRequest*)request redirectResponse:(NSURLResponse*)redirectresponse fromDataSource:(WebDataSource*)dataSource {
        NSLog(@"willSendRequest delegate method called");
    }
    

    如果您实现了这么多,您应该会在运行应用程序时看到日志语句在控制台中回显。您需要在该方法中处理重定向。正如我之前所说,我并不精通这个协议的实现。根据this 线程,它实际上可能是您想要的WebPolicyDelegate 协议。所涉及的原则将是相同的。

    【讨论】:

    • 更新了主帖,可以看看吗?
    • 天哪,我讨厌刚接触编码语言!其中一半对我来说没有任何意义,我会尝试使用它,谢谢!
    • 比我想象的更多丢失 - (NSURLRequest *)webView:(WebView *)webview resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:( WebDataSource *)dataSource { return false; } 将它添加到 webberAppDelegate.h 但它给了我一个错误,你能抽出一分钟帮助我吗?
    • 谢谢,试过加了,还是输了,加了赏金!我是 PHP/CSS/XHTML 编码员,所以这对我来说是非常新的:s
    • @interface webberAppDelegate : NSObject &lt;NSApplicationDelegate&gt; 更改为 @interface webberAppDelegate : NSObject &lt;NSApplicationDelegate,WebResourceLoadDelegate&gt;,如果您看到诊断日志消息回显到控制台,请告诉我。
    【解决方案2】:

    据我所知,这两个委托方法可以捕获其他框架/内容的 URL。您应该尝试并在您的页面上测试它们。阅读这些方法的帮助以了解如何使用这些方法。防止客户端重定向。

    // WebView delegate methods
    
    // Used to indicate that we've started loading (so that we can update our progress indicator
    // and status text field)
    - (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame
    {
        if( frame == [myWebView mainFrame] )
            NSLog(@"EntryController: Started loading mainFrame");
        else
            NSLog(@"EntryController: Started loading Frame : %@", [[frame.dataSource request] URL]); 
    }
    
    
    - (void)webView:(WebView *)sender willPerformClientRedirectToURL:(NSURL *)URL
              delay:(NSTimeInterval)seconds fireDate:(NSDate *)date
              forFrame:(WebFrame *)frame
    {
        NSLog(@"EntryController: willPerformClientRedirectToURL: %@",URL);    
    }
    

    问候 吉米

    【讨论】:

      【解决方案3】:

      虽然 jstevenco 的回答解释了如何知道 webview 是否正在尝试转到另一个 url,但它没有回答如何阻止 webview 转到此类 url。

      如果您想阻止 WebView 转到任何其他 URL,您必须实现 WebPolicyDelegate Protocol。需要注意的是,这是一个非正式的协议,所以你不能写@interface MyDelegate : NSObject &lt;WebPolicyDelegate&gt;

      而是在您的webberAppDelegate.h 中导入 Webkit:

      #import <WebKit/WebPolicyDelegate.h>
      

      webberAppDelegate.m 中实现webView:decidePolicyForNavigationAction:request:frame:decisionListener: 方法,此方法“每次遇到服务器重定向时都会调用,除非被较早的策略决定阻止”。 (WebPolicyDelegate Protocol Documentation)

      在这个方法中你需要告诉decisionListener它必须忽略任何重定向。这是实现:

       - (void)webView:(WebView *)sender decidePolicyForNavigationAction:(NSDictionary *)actionInformation
               request:(NSURLRequest *)request
                 frame:(WebFrame *)frame
      decisionListener:(id <WebPolicyDecisionListener>)listener { 
      
              [listener ignore];
      
           }
      

      但是,请注意此实现,因为您将忽略任何重定向,而且我认为这不是您想要的(它将是一个静态网页);更有可能的是,您想要的是防止重定向离开您的域,所以您真正想要的是:

       - (void)webView:(WebView *)sender decidePolicyForNavigationAction:(NSDictionary *)actionInformation
               request:(NSURLRequest *)request
                 frame:(WebFrame *)frame
      decisionListener:(id <WebPolicyDecisionListener>)listener { 
      
      
          if (![[[request URL] absoluteString] hasPrefix:@"yourdomain.com"]) {
      
              [listener ignore];
          }
      
        }
      

      【讨论】:

        【解决方案4】:

        是的,您可以这样做。实施

        – webView:shouldStartLoadWithRequest:navigationType:
        

        这个delegate 。每当您的 webview 即将发出请求时,都会调用此方法。所以现在当有人点击你网页上的按钮时,你会得到这个方法的调用。接到这个电话后,你可以选择用它做任何你想做的事情。例如通过您自己的服务器重定向链接,或向您的服务器记录有关用户活动等的请求。

        示例 - 在这里,您试图拦截在您的网页上点击的任何链接,并首先将其传递给 myMethodAction

        - (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
        { 
            if(navigationType == UIWebViewNavigationTypeLinkClicked)
            {
                 if(overrideLinksSwitch.on == TRUE)
                 {
                     [self myMethodAction];
                     [myWebView stopLoading];
                     return YES;
                 }
                else
                {
                    return YES;
                }
            }
            return YES;
        }
        

        希望这会有所帮助...

        【讨论】:

        • 在objective-c中没有那么先进,错误:在'UIWebView'之前预期')'有什么想法吗?有点迷茫
        • 顺便说一句,我不是为 iphone 制作的,这是为 mac 应用程序制作的
        • 更新了主帖,可以看看吗?
        • 您不能在 Mac 上使用 UIWebViewDelegate 方法。查看 WebKit 框架中的WebResourceLoadDelegate 协议。
        猜你喜欢
        • 2015-09-02
        • 2014-03-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-22
        • 2014-10-13
        • 2014-10-12
        相关资源
        最近更新 更多