? check the answer while webView: shouldStartLoadWithRequest: naviagiontType ... is waiting?

iPhone / ObjC

I am really stuck here and I could use some help please.

Let me explain some things first:

I have a UIWebView that loads a url. as soon as the user clicks on the link - (BOOL) webView: shouldStartLoadWithRequest: navigationType: gets the message (according to the protocol). Within this method, I can decide if the url should load into the webView or do something else with it. I am installing NSURLConnection so I can check the answer.

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

      

as soon as the application receives the response - (void) connection: didReceiveResponse: receives the message (according to the protocol) and I can parse the response there.

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

      

Now what I'm trying to do is let - (BOOL) webView: shouldStartLoadWithRequest: wait until - (void) connection: didReceiveResponse: ready.

I can work with sendSynchronousRequest: the reason is that it will download the complete file before I can check the response.

Does anyone have any ideas? Thank you in advance. or is there a better way to check the answer?

+1


source to share


1 answer


If you really want - (BOOL) webView: shouldStartLoadWithRequest: you have two options. First, you can load your data synchronously:

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

      

If you do this, you don't need to implement the delegate methods (since they won't be called). Then you just passed the response to a method that checks if you want to download.

The downside to this is that you are going to play the runloop at boot time if you do, which means the UI will become unresponsive and if you are on a slow connection the app might be killed because it will stop responding to events for too long.

Another option is to run runLoop inside 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 running runloop, you enable event handling, which allows invocations of delegate methods. Obviously, you need to determine when this is done and stop the runloop, which is what the wait IVAR is for.

Since your runloop is running, the UI will not only be able to respond to the event, but it will also be fully interactive. This means that the user can use additional links while you do so. You will need to protect yourself from this by either making your code reentrant or by disabling user interaction in anything that could cause problems.

In any case, there are many mistakes around that fit any approach. This is a really tricky thing, and unless you are an experienced Cocoa developer, I don't recommend doing this, if you can find another way to handle your upload process, it will be much easier.

+6


source







All Articles