Re: Asynchronous WSMethodInvocations [solved?]
Re: Asynchronous WSMethodInvocations [solved?]
- Subject: Re: Asynchronous WSMethodInvocations [solved?]
- From: Jordan Krushen <email@hidden>
- Date: Sun, 24 Jul 2005 18:48:27 -0700
On 7/22/05, Jordan Krushen <email@hidden> wrote:
> I've been going through Mac OS X Advanced Development Techniques, and
> have been trying to convert the XML-RPC example to an asynchronous
> one, but have failed miserably. I haven't really done any procedural
> (Carbon or CoreServices) stuff on OS X yet. I just hate blocking on
> network I/O, and would like to use the run loop instead of getting in
> its way.
Ok, I've fought with this for a couple days, and I've managed to
cobble something together that (seemingly) works. I'm unsure,
however, if some of my methods to make it work are valid, due to the
lack of examples.
Below is a pretty bare-bones example of asynchronous XML-RPC using
WebServicesCore. The NIB is a single window with two pop-ups for
input, a button to trigger the request, and some textfields for the
results.
I have this working, even to the point of being able to have the
server block for a few seconds in each request, while clicking the
action button in the window a few times, and watching all the requests
show up on time without errors. Menus (and of course, the same button
that triggers the event) are now usable while the request is waiting.
No threads, no blocking. Getting happier..
I have some questions for anyone who could give this small class a quick review:
- Is rpcContext used sanely? I tried to recreate it within
getProductInformation each time (copied from an old unanswered post
from someone else on this topic), but it would crash in
ws_retain_context (or similar), so I moved it to an ivar instead. I
admit to a lack of familiarity with using structs in objects as ivars,
especially when one of the items is a pointer to the parent object.
Is what I'm doing sufficent?
- Should I be in fact using NSDefaultRunLoopMode?
- Is using a function as callback this way the simplest / easiest way
to deal with calling back out to the object that cares? Am I missing
something important in callback()?
Any other advice?
Thanks,
J.
/* AppController.h */
#import <Cocoa/Cocoa.h>
@interface AppController : NSObject
{
IBOutlet NSPopUpButton *productPopUp;
IBOutlet NSPopUpButton *colorPopUp;
IBOutlet NSTextField *resultTextField;
IBOutlet NSTextField *priceTextField;
IBOutlet NSTextField *stockTextField;
IBOutlet NSProgressIndicator *progressIndicator;
NSURL *rpcURL;
NSString *rpcMethod;
WSClientContext rpcContext;
}
- (IBAction)getProductInformation:(id)sender;
void callback(WSMethodInvocationRef invocation, void *info,
CFDictionaryRef outRef);
- (void)methodCallBack:(NSDictionary *)result;
@end
/* AppController.m */
#import "AppController.h"
#import <CoreServices/CoreServices.h>
@implementation AppController
- (id)init
{
[super init];
if (self) {
rpcContext.info = self;
rpcURL = [[NSURL URLWithString:
@"http://localhost/~wired/product_server.php"] retain];
rpcMethod = @"example.getProductInfo";
}
return self;
}
- (void)dealloc
{
[rpcURL release];
rpcContext.info = NULL;
[super dealloc];
}
- (IBAction)getProductInformation:(id)sender
{
[progressIndicator startAnimation:self];
WSMethodInvocationRef rpcCall =
WSMethodInvocationCreate((CFURLRef)rpcURL, (CFStringRef)rpcMethod,
kWSXMLRPCProtocol);
NSString *selectedProduct = [productPopUp titleOfSelectedItem];
NSString *selectedColor = [colorPopUp titleOfSelectedItem];
NSDictionary *params = [NSDictionary
dictionaryWithObjectsAndKeys:selectedProduct, selectedProduct,
selectedColor, selectedColor, nil];
NSArray *paramsOrder = [NSArray arrayWithObjects:selectedProduct,
selectedColor, nil];
WSMethodInvocationSetParameters(rpcCall, (CFDictionaryRef)params,
(CFArrayRef)paramsOrder);
WSMethodInvocationSetCallBack(rpcCall, &callback, &rpcContext);
WSMethodInvocationScheduleWithRunLoop(rpcCall, [[NSRunLoop
currentRunLoop] getCFRunLoop], (CFStringRef)NSDefaultRunLoopMode);
}
void callback(WSMethodInvocationRef invocation, void *info,
CFDictionaryRef outRef)
{
[(AppController *)info methodCallBack:(NSDictionary *)outRef];
}
- (void)methodCallBack:(NSDictionary *)result
{
if (WSMethodResultIsFault((CFDictionaryRef)result))
{
NSRunAlertPanel([NSString stringWithFormat:@"Error %@", [result
objectForKey: (NSString*)kWSFaultCode]],
[result objectForKey: (NSString*)kWSFaultString], @"OK", @"", @"");
}
else {
NSArray *array = [result objectForKey: (NSString*)kWSMethodInvocationResult];
[resultTextField setStringValue: [array description]];
[priceTextField setStringValue: [array objectAtIndex: 2]];
[stockTextField setStringValue: [array objectAtIndex: 3]];
}
[progressIndicator stopAnimation:self];
}
@end
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden