?examine a response while webView:shouldStartLoadWithRequest:naviagiontType… waits?

后端 未结 1 1743
我在风中等你
我在风中等你 2021-02-04 22:52

iPhone/objC

I\'m really stuck here and I could use some help, please.

Let me first explain some things:

I have an UIWebView which loads an url. once the

1条回答
  •  囚心锁ツ
    2021-02-04 23:37

    If you really want - (BOOL)webView:shouldStartLoadWithRequest: you have two options. The first is that you can synchronously load your data:

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

    If you do that you don't have to implement the delegate methods (as they won't be called). You would then just pass the response into a method that checks whether or not you want to download.

    The downside to that is you are going to game the runloop while you are loading if you do that, which means the UI will become unresponsive, and if you are on a slow connection the app might get killed because it will stop responding to events for too long.

    The other option is to run your runLoop inside of the webView:shouldStartLoadWithRequest: navigationType:

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

    By executing the runloop you allow event processing to continue, which lets your delegate methods get called. Clearly you need to detect when it is done and stop running the runloop, which is what the waitingForResponse ivar is for.

    Because your runloop is running the UI will not only still be capable of responding to event, but completely interactive. That means the user could tap on more links while you are doing this. You will need to protect yourself from that, either by making your code reentrant, or by disabling user interaction for anything that will cause problems.

    Either way around there are a lot of gotchas to either approach. This is really a somewhat complicated thing, and if you are not an experienced Cocoa developer I don't recommend doing it, if you can find some other way of handling your download process it will be a lot simpler.

    0 讨论(0)
提交回复
热议问题