Tuesday 15 June 2010

ios - GCD to wait for NSURLSessionDataTask to complete -



ios - GCD to wait for NSURLSessionDataTask to complete -

i have uitableviewcontroller, phone call tableviewcontrollera, that's delegate of object, apicallerb, i've created communicate api. through nsurlsessiondatatask, apicallerb setting 1 of properties, set equal 1 of tableviewcontrollera's properties.

here's tableviewcontrollera's viewdidload method:

- (void)viewdidload { [super viewdidload]; // init instance of apicallerb apicallerb *acb = [[apicallerb alloc] init]; // set tableviewcontrollera delegate tvca.delegate = self; [acb makeapicallwithargument:self.argument]; self.property1 = acb.property2; }

my question is: what's best way to wait [acb makeapicallwithargument:self.argument] complete, self.property1 = acb.property2 work? i'm assuming gcd used (`dispatch_sync'?) but, beingness new ios/objective-c, i'm not sure utilize it. or improve move 1 or both of items elsewhere?

here's method apicallerb:

- (void)makeapicallwithargument:(nsstring *)arg { nsstring *requeststring = [nsstring stringwithformat:@"http://%@:%@@apiurl.com/json/request?arg=%@", api_username, api_key, arg]; nsurlsessionconfiguration *config = [nsurlsessionconfiguration ephemeralsessionconfiguration]; config.httpadditionalheaders = @{@"accept" : @"application/json"}; nsurlsession *urlsession = [nsurlsession sessionwithconfiguration:config delegate:self delegatequeue:nil]; nsurl *url = [nsurl urlwithstring:requeststring]; nsurlrequest *req = [nsurlrequest requestwithurl:url]; nsurlsessiondatatask *datatask = [urlsession datataskwithrequest:req completionhandler:^(nsdata *data, nsurlresponse *response, nserror *error) { nsdictionary *jsonobject = [nsjsonserialization jsonobjectwithdata:data options:0 error:nil]; nsarray *ar = [jsonobject[@"result"] objectforkey:@"results"]; self.property2 = ar; }]; [datatask resume]; }

you calling asynchronous method should employ asynchronous pattern. example, completion block implementation might like:

- (void)makeapicallwithargument:(nsstring *)arg completionhandler:(void (^)(nsarray *results, nserror *error))completionhandler { nsstring *requeststring = [nsstring stringwithformat:@"http://%@:%@@apiurl.com/json/request?arg=%@", api_username, api_key, arg]; nsurlsessionconfiguration *config = [nsurlsessionconfiguration ephemeralsessionconfiguration]; config.httpadditionalheaders = @{@"accept" : @"application/json"}; nsurlsession *urlsession = [nsurlsession sessionwithconfiguration:config delegate:self delegatequeue:nil]; nsurl *url = [nsurl urlwithstring:requeststring]; nsurlrequest *req = [nsurlrequest requestwithurl:url]; nsurlsessiondatatask *datatask = [urlsession datataskwithrequest:req completionhandler:^(nsdata *data, nsurlresponse *response, nserror *error) { if (completionhandler) { if (error) { dispatch_async(dispatch_get_main_queue(), ^{ completionhandler(nil, error); }); } else { nserror *parseerror; nsdictionary *jsonobject = [nsjsonserialization jsonobjectwithdata:data options:0 error:&parseerror]; dispatch_async(dispatch_get_main_queue(), ^{ completionhandler(jsonobject[@"result"][@"results"], parseerror); }); } } }]; [datatask resume]; }

and you'd phone call like:

[acb makeapicallwithargument:self.argument completionhandler:^(nsarray *results, nserror *error){ // you'd first check create sure didn't have error self.property1 = results; }];

a couple of minor observations:

i wouldn't create new session every time. save session future requests if expect more 1 call.

your makeapicallwithargument updating property, trying retrieve later. i'd retire property , pass values parameters completion block.

i've added little error handling in this.

your [jsonobject[@"result"] objectforkey:@"results"] doesn't right. have json returns dictionary key of "result" , within dictionary key of "results". if so, fine, looks suspicious. , if json format, i'd simplify jsonobject[@"result"][@"results"].

elsewhere suggested might consider semaphores. that's bad idea. that's used create asynchronous method behave synchronously. never want block main queue.

using completion block pattern eliminates need semaphores. apple provides asynchronous api reason, should adopt asynchronous patterns when using it.

ios objective-c grand-central-dispatch

No comments:

Post a Comment