NSURLConnection sendAsynchronousRequest:queue:completionHandler: making multiple requests in a row? - objective-c

I have been using NSURLConnection's sendAsynchronousRequest:queue:completionHandler: method which is great. But, I now need to make multiple requests in a row.
How can I do this while still using this great asychronous method?

There's lots of ways you can do this depending on the behavior you want.
You can send a bunch of asynchronous requests at once, track the number of requests that have been completed, and do something once they're all done:
NSInteger outstandingRequests = [requestsArray count];
for (NSURLRequest *request in requestsArray) {
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
[self doSomethingWithData:data];
outstandingRequests--;
if (outstandingRequests == 0) {
[self doSomethingElse];
}
}];
}
You could chain the blocks together:
NSMutableArray *dataArray = [NSMutableArray array];
__block (^handler)(NSURLResponse *response, NSData *data, NSError *error);
NSInteger currentRequestIndex = 0;
handler = ^{
[dataArray addObject:data];
currentRequestIndex++;
if (currentRequestIndex < [requestsArray count]) {
[NSURLConnection sendAsynchronousRequest:[requestsArray objectAtIndex:currentRequestIndex]
queue:[NSOperationQueue mainQueue]
completionHandler:handler];
} else {
[self doSomethingElse];
}
};
[NSURLConnection sendAsynchronousRequest:[requestsArray objectAtIndex:0]
queue:[NSOperationQueue mainQueue]
completionHandler:handler];
Or you could do all the requests synchronously in an ansynchronous block:
dispatch_queue_t callerQueue = dispatch_get_current_queue();
dispatch_queue_t downloadQueue = dispatch_queue_create("Lots of requests", NULL);
dispatch_async(downloadQueue, ^{
for (NSRURLRequest *request in requestsArray) {
[dataArray addObject:[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]];
}
dispatch_async(callerQueue, ^{
[self doSomethingWithDataArray:dataArray];
});
});
});
P.S. If you use any of these you should add some error checking.

Related

objective c invisible array out of function param request

I'm triyng to get array from server. But it doesn't work. I'm mean in the function everything is okay with my array but out of it it's null. How to fix?
for(int i=1; i<5; i++){
NSString *category = [NSString stringWithFormat:#"%d",i];
NSString *encrypt = #"encrypt=93mrLIMApU1lNM619WzZje4S9EeI4L2L";
NSString *latitude = #"latitude=32.794044";
NSString *longtitude = #"longitude=34.989571";
NSString *params = [NSString stringWithFormat:#"%#&category=%#&%#&%#&area=CENTER",
encrypt,category,latitude,longtitude];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:#"http://admin.t-club.co.il/api/get-buissness"]];
NSData *postBody = [params dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:postBody];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError)
{
if(!connectionError)
{
_myDict =[NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
_tmpArray = [_myDict objectForKey:#"result"];
NSLog(#"my array %#",_tmpArray);//here array isn't null
}
}];
[_myArray addObjectsFromArray:_tmpArray];
}
NSLog(#"my array %#",_tmpArray);//here is null
It looks like what you're aiming for is to make several async requests in sequence. This can be done by adding a little abstraction.
First, a method that makes just one request and provides a dictionary in response of the parsed JSON result...
- (void)makeRequestWithParams:(NSString *)params completion:(void (^)(NSDictionary *, NSError *))completion {
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:#"http://admin.t-club.co.il/api/get-buissness"]];
NSData *postBody = [params dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:postBody];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
if(!connectionError) {
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
completion(dictionary, nil);
} else {
completion(nil, connectionError);
}
}];
}
Please note that the NSURLConnnection methods have been replaced by NSSession, so this code will need to change to that soon.
Now something that calls that first method over and over. This one takes an array of request parameters as input, fills a mutable array with the dictionary results, and calls a completion block when its done...
- (void)makeManyRequestsWithParams:(NSArray *)arrayOfParams fillingArray:(NSMutableArray *)result completion:(void (^)(BOOL))completion {
if (arrayOfParams.count == 0) return completion(YES);
NSString *nextParams = arrayOfParams[0];
[self makeRequestWithParams:nextParams completion:^(NSDictionary *dictionary, NSError *error) {
if (!error && dictionary) {
[result addObject:dictionary];
NSArray *remainingParams = [arrayOfParams subarrayWithRange:NSMakeRange(1, arrayOfParams.count-1)];
[self makeManyRequestsWithParams:remainingParams fillingArray:result completion:completion];
} else {
completion(NO);
}
}];
}
Finally, your original loop's job is now limited to just assembling the parameters. Once those are in an array, call to make the requests...
- (void)test {
NSMutableArray *arrayOfParams = [NSMutableArray array];
for(int i=1; i<5; i++){
NSString *category = [NSString stringWithFormat:#"%d",i];
NSString *encrypt = #"encrypt=93mrLIMApU1lNM619WzZje4S9EeI4L2L";
NSString *latitude = #"latitude=32.794044";
NSString *longtitude = #"longitude=34.989571";
NSString *params = [NSString stringWithFormat:#"%#&category=%#&%#&%#&area=CENTER",
encrypt,category,latitude,longtitude];
[arrayOfParams addObject:params];
}
NSMutableArray *result = [NSMutableArray array];
[self makeManyRequestsWithParams:arrayOfParams fillingArray:result completion:^(BOOL success) {
if (success) {
NSLog(#"all done, result is %#", result);
} else {
NSLog(#"sadness");
}
}];
// don't expect results to be ready here. they won't be.
// see how they are logged above in the completion block?
}
NSURLConnection sendAsynchronousRequest is asynchronous meaning it will be moved to a background thread and execution will continue without waiting for the task to complete. So by the time it gets to your bottom NSLog, the request will still be processing and the value of _tmpArray will be null.
You can use sendSynchronousRequest to have the request complete before moving on.
http://codewithchris.com/tutorial-how-to-use-ios-nsurlconnection-by-example/#synchronous

how I can Modify this code

I'm using this function to send a request to a server and receive JSON response in an NSDictionary.
- (void)performRequest:(NSString *)aRequest
{
NSString *string=[NSString stringWithFormat:#"%#%#",baseURL,aRequest];
NSURL *url = [NSURL URLWithString: string];
NSLog(#"string%#",string);
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response,
NSData *data, NSError *connectionError)
{
if (data.length > 0 && connectionError == nil)
{
NSDictionary * greeting = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
NSLog(#"%#",greeting2);
}
}];
}
What I want is to modify it so that it remains a function sending service URL and a separate one where the JSON response comes at a NSDictionary so you can reuse them in other classes.
I used the networking introduced by iOS 7: NSURLSession. This is the networking code I use in a project. But I would suggest you to use AFNetworking instead. That will save you more time on it. It depends on what you want in your application.
+ (void)requestOperationWithMethod:(NSString *)method
withUrl:(NSString *)url
header:(NSDictionary *)header
params:(NSDictionary *)params
completion:(FHCompletionResultBlock)completion {
FHNetworking *network = [FHNetworking shareNetworking];
NSData *bodyData;
NSError *jsonError = nil;
NSData *data = [NSJSONSerialization dataWithJSONObject:params options:kNilOptions error:&jsonError];
if (!jsonError) {
bodyData = data;
}
// prepare http request header and body data fields
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
for (NSString *key in header.allKeys) {
[request setValue:header[key] forHTTPHeaderField:key];
}
[request setHTTPMethod:method];
[request setHTTPBody:bodyData];
[request setTimeoutInterval:30.0f];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
[[network.session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
NSError *jsonError = nil;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];
if (jsonError)
completion(nil, jsonError);
else {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (httpResponse.statusCode >= 400) {
if (json[#"code"] && json[#"error"]) {
NSError *error = [NSError errorWithDomain:#"Error" code:[json[#"code"] integerValue] userInfo:#{NSLocalizedDescriptionKey: NSLocalizedString(json[#"error"], nil)}];
completion(nil, error);
}
else {
NSError *error = [NSError errorWithDomain:#"Error" code:-1 userInfo:#{NSLocalizedDescriptionKey: NSLocalizedString(#"Unknown error", nil)}];
completion(nil, error);
}
}
else {
completion(json, nil);
}
}
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}] resume];
}
You can change your method to take a completionHandler parameter, itself:
- (void)performRequest:(NSString *)aRequest completionHandler:(void(^)(NSDictionary *responseObject, NSError *error))completionHandler
{
NSString *string=[NSString stringWithFormat:#"%#%#",baseURL,aRequest];
NSURL *url = [NSURL URLWithString: string];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response,
NSData *data, NSError *connectionError) {
if (data.length > 0 && connectionError == nil) {
NSError *parseError;
NSDictionary *responseObject = [NSJSONSerialization JSONObjectWithData:data
options:0
error:&parseError];
completionHandler(responseObject, parseError);
} else {
completionHandler(nil, error);
}
}];
}
Now you can call it and supply whatever you want in the completion handler:
[self performRequest:requestString completionHandler:^(NSDictionary *responseObject, NSError *error) {
if (responseObject) {
// everything is good; use your NSDictionary here
} else {
// handle error here
}
}];

How to show JSON data in UIView labels

About every single tutorial and example on the internet I see shows how to fetch JSON from some url and show it in Tableview. This is not my problem I know how to do that with AFNetworking framework or with native APIs.
My problem is that after I have downloaded the JSON, I want to show some of it in my UIView labels. I have actually succeeded doing this when I was trying to find a way around NSURLSession inability to cache in iOS 8. But I didn't realize that it was synchronous.
Factory.m
+ (Factory *)responseJson
{
static Factory *shared = nil;
shared = [[Factory alloc] init];
NSHTTPURLResponse *response = nil;
NSString *jsonUrlString = [NSString stringWithFormat:#"http://urltojson.com/file.json"];
NSURL *url = [NSURL URLWithString:[jsonUrlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSError *error = nil;
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReturnCacheDataElseLoad
timeoutInterval:10.0];
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (error) {
NSLog(#"error");
} else {
//-- JSON Parsing
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:nil];
//NSLog(#"Result = %#",result);
shared.responseJson = result;
}
return shared;
}
My question is that is it possible to use for example AFNetwoking to do the same thing? Am I missing some method that I need to call like in case of a TableView
[self.tableView reloadData];
I would like to use that framework because I need to check Reachability and it seems to implement it already.
Edit as asked to show more code
ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
[self factoryLoad];
[self setupView];
}
- (void)factoryLoad
{
Factory *shared = [Factory responseJson];
self.titles = [shared.responseJson valueForKeyPath:#"data.title"];
dispatch_async(dispatch_get_main_queue(), ^{
[self.collectionView reloadData];
});
}
- (void)setupView
{
self.issueTitleLabel.text = [self.titles objectAtIndex:0];
}
There are a couple oddities in the code you posted.
Factory, which appears to be a singleton class, should be instantiated inside a dispatch_once to ensure thread safety.
In ViewController.m, you are calling factoryLoad on the main thread, which is subsequently calling sendSynchronousRequest on the main thread. Apple's NSURLConnection Documentation warns against calling this function on the main thread as it blocks the thread, making your application unresponsive to user input.
You should not be passing in nil as the error parameter in NSJSONSerialization JSONObjectWithData:.
In your case I would recommend separating the fetching of data from the construction of your singleton object.
Factory.m
+(Factory *)sharedFactory {
static Factory *sharedFactory = nil;
dispatch_once_t onceToken;
dispatch_once(&onceToken, {
sharedFactory = [[Factory alloc] init];
});
}
-(void)fetchDataInBackgroundWithCompletionHandler:(void(^)(NSURLResponse *response,
NSData *data,
NSError *error)
completion {
NSHTTPURLResponse *response = nil;
NSString *jsonUrlString = [NSString stringWithFormat:#"http://urltojson.com/file.json"];
NSURL *url = [NSURL URLWithString:[jsonUrlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReturnCacheDataElseLoad
timeoutInterval:10.0];
NSOperationQueue *downloadQueue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request
queue:downloadQueue
completionHandler:completion];
}
Now you should be able to create a reference to the data with a guarantee that the download request has finished and thus the data will exist.
ViewController.m
-(void)factoryLoad {
[[Factory sharedFactory] fetchDataInBackgroundWithCompletionHandler:^(void)(NSURLResponse *response, NSData *data, NSError *error){
if(!error) {
NSError *error2;
NSDictionary *serializedData = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error2];
if(error2){ /* handle error */ }
self.titles = [serializedData valueForKeyPath:#"data.title"];
[Factory sharedFactory].responseJSON = serializedData;
}
else {
// handle error
}
}];
}
This will guarantee that the download has completed before you try to access any of the downloaded information. However, I've left a few things out here, including any sort of activity indicator displaying to the user that the app is doing something important in the background. The rest is, uh, left as an exercise to the reader.
Ok I took a deeper investigation into Morgan Chen's answer and how to block.
The example code took some modification but I think It works as it should and is better code.
In Factory.m
+ (Factory *) sharedInstance
{
static Factory *_sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedInstance = [[self alloc] init];
});
return _sharedInstance;
}
-(void)fetchDataInBackgroundWithCompletionHandler: (void(^)(BOOL success, NSDictionary *data, NSError *error)) block
{
NSString * baseURL = #"http://jsonurl.com/file.json";
AFHTTPRequestOperationManager * manager = [[AFHTTPRequestOperationManager alloc] init];
__weak AFHTTPRequestOperationManager *weakManager = manager;
NSOperationQueue *operationQueue = manager.operationQueue;
[manager.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status) {
case AFNetworkReachabilityStatusReachableViaWWAN:
case AFNetworkReachabilityStatusReachableViaWiFi:
NSLog(#"internet!");
[weakManager.requestSerializer setCachePolicy:NSURLRequestReloadIgnoringCacheData];
[operationQueue setSuspended:NO];
break;
case AFNetworkReachabilityStatusNotReachable:
NSLog(#"no internet");
[weakManager.requestSerializer setCachePolicy:NSURLRequestReturnCacheDataElseLoad];
[operationQueue setSuspended:YES];
break;
default:
break;
}
}];
[manager.reachabilityManager startMonitoring];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager GET:baseURL parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
if (responseObject && [responseObject isKindOfClass:[NSDictionary class]]) {
block(YES, responseObject, nil);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { // invalid request.
NSLog(#"%#", error.localizedDescription);
block(NO, nil, error);
}];
}
In ViewController.m I call this method on viewDidLoad
-(void)factoryLoad
{
[[Factory sharedInstance] fetchDataInBackgroundWithCompletionHandler:^(BOOL success, NSDictionary *data, NSError *error) {
if (success) {
NSLog(#"we have stuff");
self.responseData = data;
self.titles = [self.responseData valueForKeyPath:#"data.title"];
[self setupView];
dispatch_async(dispatch_get_main_queue(), ^{
[self.collectionView reloadData];
});
}
}];
}

Nested NSURLSessionDataTask on background thread

My Code works just fine. What I need help, or clarification on is Nested NSURLSessionDataTask instances.
I'm making two asynchronously calls, the second call is dependent on the first.
So I make the first NSURLSessionDataTask (firstUrlCall) call which returns an array of objects. For each object in my array I then call the second NSURLSessionDataTask (secondUrlCall) and pass in a dataID.
As I mentioned before, it works. I just see alot of lines repeated and REPEATED CODE IS NOT SEXY!!!
So is there anything I can do to prevent this catastrophe? I need my code to be SEXY!
#property (nonatomic, strong) NSURLSession *Session;
FIRST CALL
-(void) firstUrlCall {
NSString *urlString = #"https://api.FIRSTURLCALL.com";
NSURLSessionDataTask *dataTask = [session
dataTaskWithURL:[NSURL URLWithString:urlString]
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (!error) {
NSDictionary *returnData = [NSJSONSerialization JSONObjectWithData:data
options:0
error:nil];
[returnData enumerateKeysAndObjectsUsingBlock:^(id dataID, id obj, BOOL *stop) {
/*
-->here is where I call secondUrlCall<--
*/
[self secondUrlCall:dataID];
}];
}
});
}];
[dataTask resume];
}
SECOND CALL
-(void) secondUrlCall:(NSString *)dataID {
NSString *urlString = [NSString stringWithFormat:#"https://api.SECONDURLCALL.com?dataID=%#",dataID];
NSURLSessionDataTask *dataTask = [session
dataTaskWithURL:[NSURL URLWithString:urlString]
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (!error) {
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data
options:0
error:nil];
if ([[json objectForKey:#"type"] isEqualToString:#"sexy"]) {
[tableArray addObject:json];
// Reload table data
[self.tableView reloadData];
}
}
});
}];
[dataTask resume];
}
PS: Sorry if you were offended from my extensive use of the word SEXY :)
Oh my goodness! What if the network is intermittent or goes down half way through?
I would take the results of the first call and put each one into an operation queue, then when processing each operation if it fails you can re-queue it.

How to get variable which is return from method

I have two methods and I need to use a variable from first as input parameter in the second. How can I do it? My code is :
First method
-(NSString*)getResponseData :(NSString*) apiHttp {
NSString *code = #"&code=";
NSString *finalLink = [[NSString alloc] initWithFormat:#"%#%#",apiHttp,phoneNumber];
NSURLRequest *request = [NSURLRequest requestWithURL:
[NSURL URLWithString:finalLink]];
NSLog(#"%#", finalLink);
__block NSDictionary *json;
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
json = [NSJSONSerialization JSONObjectWithData:data
options:0
error:nil];
NSLog(#"Async JSON: %#", json);
NSError *error;
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
myString = [jsonDict objectForKey:#"result"];
// NSLog(#"%#", myString);
}];
return myString;
}
Second method:
-(void)showCodeView:(NSString*) ifString{
if([ifString isEqualToString:#"200"]){
aPasswordField.hidden = NO;
[aPasswordField setBorderStyle:UITextBorderStyleLine];
aPasswordField.layer.cornerRadius=1.0f;
aPasswordField.layer.masksToBounds=YES;
aPasswordField.layer.borderColor=[[UIColor whiteColor]CGColor];
aPasswordField.layer.borderWidth= 0.8f;
UIColor *color = [UIColor lightTextColor];
aPasswordField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:#"Код" attributes:#{NSForegroundColorAttributeName: color}];
self.aPasswordField.delegate = self;
}
}
And this is how I call them:
[self getResponseData:apiHttp];
[self showCodeView:myString];
So I can't understand why my myString is null after [self getResponseData:apiHttp]; was called even if my method retutns it.
You are calling two methods after another but are missing that the first one is asynchronous.
When you call sendAsynchronousRequest:queue:completionHandler: it will perform the request asynchronously (not waiting) and call the completion block once it has a response. Since the code doesn't wait for this to happen, getResponseData: immediately returns the current value of myString which is nil if it's not set yet.
You can see how this is working by adding a some log statements before and after each method call:
NSLog(#"Before getResponseData:");
[self getResponseData:apiHttp];
NSLog(#"After getResponseData:");
NSLog(#"Before showCodeView:");
[self showCodeView:myString];
NSLog(#"After showCodeView:");
and the same for the asynchronous request
NSLog(#"Before sendAsynchronousRequest:");
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response,
NSData *data,
NSError *connectionError) {
NSLog(#"After sendAsynchronousRequest:");
// the rest of the completion block ...
There are many ways to deal with this. One would be to add a block argument for the getResponseData: method that is called from the completion handler of the request.
If you are unused to working with blocks, a simpler but more tightly coupled alternative is to call [self showCodeView:myString]; from inside of the completion handler.
You want to perform showCodeView only when your asynchronous getResponseData finishes, so implement your own rendition of the completion block pattern:
- (void)getResponseData :(NSString*) apiHttp completionHandler:(void (^)(NSDictionary *, NSError *))completion {
NSString *code = #"&code=";
NSString *finalLink = [[NSString alloc] initWithFormat:#"%#%#",apiHttp,phoneNumber];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:finalLink]];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (completion) {
if (connectionError) {
completion(nil, connectionError);
} else {
NSError *parseError;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
completion(json, parseError);
}
}
}];
}
Note, I've eliminated that __block variable and changed the return type to void (since this doesn't return anything ... the value is passed back via the completion block).
You can then do:
[self getResponseData:apiHttp completionHandler:^(NSDictionary *json, NSError *error) {
if (error) {
// handle this however appropriate for your app
} else {
NSString *myString = json[#"result"];
[self showCodeView:myString];
}
}];