1

iPhone/objC

我真的被困在这里,我可以使用一些帮助,拜托。

让我先解释一些事情:

我有一个加载 url 的 UIWebView。一旦用户单击链接 - (BOOL)webView:shouldStartLoadWithRequest:navigationType: 获取消息(根据协议)。在这个方法中,我可以决定是否应该在 webView 中加载 url 或者用它做其他事情。我正在建立一个 NSURLConnection 以便我可以检查响应。

- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request
 navigationType:(UIWebViewNavigationType)navigationType {

    NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    if (theConnection) {
        NSLog(@" Connection established");
        receivedDataFromConnection = [[NSMutableData data] retain];
        }
    else {
        NSLog(@"Connection failed");
    }   


    if (downloadYESorNO == YES) {
        NSLog(@"Do the download");
        return NO;
    }
    else {
        NSLog(@"will show in webView");
        return YES;
    }
}

一旦应用程序收到响应 - (void)connection:didReceiveResponse: 收到一条消息(根据协议),我就可以在那里分析响应。

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{      
        NSString *MIME = response.MIMEType;
        NSString *appDirectory = [[NSBundle mainBundle] bundlePath];
        NSString *pathMIMETYPESplist = [appDirectory stringByAppendingPathComponent:@"MIMETYPES.plist"];

        NSArray *displayMIMETypes = [NSArray arrayWithContentsOfFile: pathMIMETYPESplist];
        BOOL *asdf = [displayMIMETypes containsObject:MIME];

        if (asdf == YES) {
            downloadYESorNO =NO;
        }
        else {
            downloadYESorNO = YES;
        }

        [receivedDataFromConnection setLength:0];
        [connection release];

现在我想要实现的是让 - (BOOL)webView:shouldStartLoadWithRequest: 等到 -(void)connection:didReceiveResponse: 准备好。

我可以使用 sendSynchronousRequest: 因为它会在我检查响应之前下载完整的文件。

有人有想法吗?提前致谢。还是有更好的方法来检查响应?

4

1 回答 1

6

如果你真的想要 - (BOOL)webView:shouldStartLoadWithRequest: 你有两个选择。首先是您可以同步加载数据:

NSData * receivedDataFromConnection = [NSURLConnection sendSynchronousRequest: request  returningResponse:&response error:&error];

如果你这样做,你就不必实现委托方法(因为它们不会被调用)。然后,您只需将响应传递给检查您是否要下载的方法。

不利的一面是,如果这样做,您将在加载时玩运行循环,这意味着 UI 将变得无响应,并且如果您的连接速度较慢,则应用程序可能会被终止,因为它将停止响应事件太长。

另一种选择是在 webView:shouldStartLoadWithRequest:navigationType: 内运行 runLoop:

- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request
 navigationType:(UIWebViewNavigationType)navigationType {

    NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    if (theConnection) {
        NSLog(@" Connection established");
        receivedDataFromConnection = [[NSMutableData data] retain];
        }
    else {
        NSLog(@"Connection failed");
    }   

     waitingForResponse = YES;
     while (waitingForResponse) {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        [pool drain];
    }


    if (downloadYESorNO == YES) {
        NSLog(@"Do the download");
        return NO;
    }
    else {
        NSLog(@"will show in webView");
        return YES;
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{      
    NSString *MIME = response.MIMEType;
    NSString *appDirectory = [[NSBundle mainBundle] bundlePath];
    NSString *pathMIMETYPESplist = [appDirectory stringByAppendingPathComponent:@"MIMETYPES.plist"];

   NSArray *displayMIMETypes = [NSArray arrayWithContentsOfFile: pathMIMETYPESplist];
   BOOL *asdf = [displayMIMETypes containsObject:MIME];

   if (asdf == YES) {
         downloadYESorNO =NO;
   } else {
        downloadYESorNO = YES;
   }

   [receivedDataFromConnection setLength:0];
   [connection release];
   waitingForResponse = NO;
}

通过执行运行循环,您可以继续处理事件,从而调用您的委托方法。显然,您需要检测它何时完成并停止运行 runloop,这就是 waitingForResponse ivar 的用途。

因为你的 runloop 正在运行,所以 UI 不仅仍然能够响应事件,而且完全可以交互。这意味着用户可以在您执行此操作时点击更多链接。您需要通过使您的代码可重入或禁用任何会导致问题的用户交互来保护自己免受这种情况的影响。

无论哪种方式,这两种方法都有很多陷阱。这确实是一件有点复杂的事情,如果你不是一个有经验的 Cocoa 开发者我不建议你这样做,如果你能找到一些其他的方式来处理你的下载过程会简单很多。

于 2009-07-24T20:11:07.717 回答