tags:

views:

5240

answers:

3

Why doesn't this code work? It shows the Google screen but it doesn't change the text box value. I confirmed that the JS does work by running it in Safari, and this code seems to work otherwise since running alert('hi') does work.

NSURL *web_url = [NSURL URLWithString:@"http://www.google.com"];
NSURLRequest *web_request = [NSURLRequest requestWithURL:web_url];
[web_screen loadRequest:web_request];
NSString *js_result = [web_screen stringByEvaluatingJavaScriptFromString:@"document.getElementsByTagName('input')[1].value='test';"];
+1  A: 

Does it work if you wait for the page to finish loading first?

Chris Lundie
That is definitely the problem.
Sam Soffes
+2  A: 

Consider looking at NSURLConnection and its delegate methods. You can use these to check on the status of a download.

@interface 
...
NSURLConnection *connectionInProgress;
NSData *googleRequestResponseData;
NSURL *googleURL;
...

@implementation
...
- (void) setUpRequest {
  googleURL = [[NSURL URLWithString:@"http://www.google.com/"] retain];
  googleRequestResponseData = [[NSMutableData data] retain];
  NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:30.0];
  connectionInProgress = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
}

#pragma mark NSURLConnection delegate methods

- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
   [googleRequestResponseData appendData:data];
}

- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
   [web_screen loadData:googleRequestResponseData MIMEType:@"application/octet-stream" textEncodingName:@"utf-8" baseURL:googleURL];
   NSString *js_result = [web_screen stringByEvaluatingJavaScriptFromString:@"document.getElementsByTagName('input')[1].value='test';"];
   NSLog (js_result);

   [googleURL release];
   [googleRequestResponseData release];
   [connectionInProgress release];
   connectionInProgress = nil;
}

- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
   NSLog (@"Connection failed to load data from Google!");
   [googleURL release];
   [googleRequestResponseData release];
   [connectionInProgress release];
   connectionInProgress = nil;
}

Alternatively, check out Ben Copsey's ASIHTTPRequest wrapper, which includes a simplified approach to asynchronous downloads (see ASINetworkQueue, specifically).

You can use ASINetworkQueue to run a method of your choice (to run the Javascript code, for example), once the request download is complete.

Alex Reynolds
+1  A: 

The Load URL action takes place asynchronously. It does not even start until your method has ended. So your javascript is being pushed into an empty UIWebView, then your method ends, then the load happens.

You need to let your method end before the js is pushed in. The standard approach for this is to use a Delegate object, which will have a method called on it when the load completes. Only then does it make sense to push in the javascript.

Justin