1

I decided I would change how I implement printing in my Cocoa app by having my app provide string-data to a webpage in an embedded webview, and then I would print that webview/frame.

The problem is that my code isn't being called and I don't see an error being returned.

Here is the setup:

1) Use Dashcode and build a webpage. There is no "form" container in the generated document, but it has fields like this:

   <input id="customerNameField" type="text" name="" value="">
    <input id="customerStreetField" type="text" name="" value="">

2) In IB, I create a window, toss in a WebView, link it to an outlet in my controller and create an NSURLRequest, grab my WebView's mainFrame and have it load the request. That works, the page is displayed in the WebView. Code:

 [[wv mainFrame] stopLoading];     

 request = [NSURLRequest requestWithURL:currentPrintTemplateURL];

 [[wv mainFrame] loadRequest:request];

3) I want to set the value of the customerNameField in my webView, so I do the following:

3A) Use a class-method on my controller that allows all keys to be accessible to the bridge:

+(BOOL)isKeyExcludedFromWebScript:(const char *)name {

 // TODO: Implement specific blocks here; but for now let it all through

 NSLog(@"Excluding nothing from WebScript");

 return NO;

}

3B) Add a JavaScript function to my HTML file, which I want to call with arguments from Cocoa:

function populateRepairFields(repairCase) {
 document.getElementById("customerNameField").value = repairCase;
 }

(I know the javascript single-line-of-code works because I can add a button to my page, trigger the function in onClick and the code modifies the value of the customerNamefield.)

3C) Ask the webview for it's windowScriptObject, create an NSArray of arguments to be passed to the javascript function, and then execute them using the callWebScriptMethod method:

     // grab the data we want to send to the javascript     
    NSString *customerFirstName = [self valueForKeyPath:@"currentRepairCase.customer.firstName"];

 NSLog(@"(debug) Ensure we have a value - customerFirstName = %@", customerFirstName);

 // build the array whose items will be passed as arguments to the javascript method

   NSArray * args = [NSArray arrayWithObjects:customerFirstName, nil]; 

// get the windowScriptObject, then (debug) log the output so we can be sure it is not null

  ws = [wv windowScriptObject];


 NSLog(@"WebScriptObject = %@", ws);


//Then call the javascript method via the bridge, logging the output so we can see if there is an WSUndefined error returned (results are the same even if we don't wrap it in an NSLog)

     NSLog(@"WS ERR: %@", [ws callWebScriptMethod:@"populateRepairFields" withArguments:args]);  

4) All that. And .. nothing. I don't see the class method being called (3A), and don't get an WSUndefined or any other error message (3C), and I don't see an alert if I tried to add a javascript alert in my code.

I thought maybe I would need to setup a delegate for the WebView, but after checking the docs, I don't see a delegate requirement for WebScript. (I then connected all the delegate outlets to my controller, but that didn't help.)

Why is my code not seemingly being called? What's missing?

Thanks..

2
  • 1
    Mmm... I made a sample app and copied your code, and it worked without any problem. From where you performed your step 3C ? The only thing I can think of is that you called 3C before webview is ready. (URL loading takes some event cycles, even though it's a local file.) I called it from an IBAction attached to an NSButton. Commented Feb 12, 2010 at 22:49
  • Thank you, Yuji. That was the problem. I moved the Javascript call out to a WebView delegate method that's called after a frame finishes loading, thus ensuring the webview was ready. It works. Yay! Delegate used: // added before the last line of Step 2: [wv setFrameLoadDelegate:self]; // contains all code from 3C: - (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame; Commented Feb 13, 2010 at 0:55

1 Answer 1

2

You can only use the WebScriptObject instance after the WebView instance is ready, and the WebView instance is not ready right after your call

 [[wv mainFrame] loadRequest:request];

because the loading is done in the background thread automatically by WebKit. Your code should work as is, as long as you call it shortly afterwards from the webview delegate, action methods, etc.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.