1
votes
-(void) conn:(NSString *)method{

dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
    __block NSDictionary *resultBlock = nil;
    dispatch_sync(concurrentQueue, ^{
        /* Download the json here */

        //Create webservice address
        NSString *webService = [_baseURL stringByAppendingString:_webService];
        //NSLog(@"%@", webService);
        //Create error object
        NSError *downloadError = nil;

        //Create the request
        NSMutableURLRequest *req = [self initRequest:webService method:method];

        if(req != nil){
            //Request the json data from the server
            NSData *jsonData = [NSURLConnection
                                    sendSynchronousRequest:req
                                    returningResponse:nil
                                    error:&downloadError];

            if(downloadError!=nil){
                NSLog(@"DOWNLOAD ERROR %@", downloadError);
            }

            NSError *error = nil;
            id jsonObject = nil;

            if(jsonData !=nil){

                /* Now try to deserialize the JSON object into a dictionary */
                jsonObject = [NSJSONSerialization
                                 JSONObjectWithData:jsonData
                                 options:kNilOptions
                                 error: &error];
            }


            //Handel the deserialized object data
            if (jsonObject != nil && error == nil){
                NSLog(@"Successfully deserialized...");
                if ([jsonObject isKindOfClass:[NSDictionary class]]){
                    resultBlock = (NSDictionary *)jsonObject;
                    //NSLog(@"Deserialized JSON Dictionary = %@", resultBlock);
                }
                else if ([jsonObject isKindOfClass:[NSArray class]]){
                    NSArray *deserializedArray = (NSArray *)jsonObject;
                    NSLog(@"Deserialized JSON Array = %@", deserializedArray);
                } else {
                    /* Some other object was returned. We don't know how to deal
                     with this situation, as the deserializer returns only dictionaries
                     or arrays */
                }
            }
            else if (error != nil){
                NSLog(@"An error happened while deserializing the JSON data. %@", error);
            }else{
                NSLog(@"No data could get downloaded from the URL.");
                //[self conn:method];
            }
        }
    });
    dispatch_sync(dispatch_get_main_queue(), ^{

        /* Check if the resultBlock is not nil*/
        if(resultBlock != nil){
            /*Set the value of result. This will notify the observer*/
            [self setResult:resultBlock];
        }
    });
});
}

Why do I get the following error?

An error happened while deserializing the JSON data. Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.) UserInfo=0x20839f80 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}

When I change it to

  /* Now try to deserialize the JSON object into a dictionary */
                jsonObject = [NSJSONSerialization
                                 JSONObjectWithData:jsonData
                                 options:NSJSONReadingAllowFragments
                                 error: &error];
            }

I get the following error:

An error happened while deserializing the JSON data. Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (Invalid value around character 0.) UserInfo=0x20888760 {NSDebugDescription=Invalid value around character 0.}

I changed my connection from LTE to wifi and now I get 504 error and NSLog(@"No data could get downloaded from the URL.");

1
Well it seems that your JSON is invalid, you can use an online tool to validate it such as this oneAlladinian
I validated the json and it is goodwwjdm
Can you test your code on other JSON?stosha
I already wrote a JSON parser. I just need to try to deserialize the JSON object into a dictionary, but I get 504 error meaning there is probably something wrong with the server.wwjdm
Much as it galls me to do it, I have to give you +1 for actually checking the error value.Hot Licks

1 Answers

1
votes

You should fix these issues in your code first:

  1. Properly check for errors in methods which provide a pointer to a reference to an NSError object as the last parameter, e.g.: - (BOOL) doSomething:(NSError**)error, or -(NSData*) doSomething:(NSError**)error

    In order test for an error correctly, you have to check the return value of the method only. Those methods indicate an error condition with a "special return value". For example, they return NO or nil - as always specified in the documentation. Only after the method indicated an error, the provided error parameter contains a meaningful value - that is, it points to an NSError object created by the method. Note that this parameter may also become none NULL when the method succeeded, in which case that has no "meaning".

  2. Web services usually can provide several formats of the requested resource. If you don't specify which format you want the server to encode the resource, you get a default format - which is not necessarily JSON.

    In order to be explicit about the desired format of the resource, set a corresponding "Accept" header. For example, if you wish the format in JSON you would set a header: "Accept: application/json" in your request.

  3. Web services may have reasons not to respond with the resource you requested. In order to be sure you got the response that you requested, you need to check the response for status code and MIME type in order to ensure you actually received a JSON response.

  4. It seems, you are a bit uncertain about how to use dispatch functions to your advantage. If you use the synchronous convenient method sendSynchronousRequest:... You certainly need to wrap it in only one dispatch_async function. If you then want to set the result on the main thread, you certainly want to use dispatch_async, not dispatch_sync.

    However, it would be an improvement if you would use sendAsynchronousRequest:... instead. And only if you would use NSURLConnection in asynchronous mode and implement the NSURLConnection delegate methods - which I strongly recommend - it would actually become great ;)

So, I think, once you fixed your code, you may be able to answer the original question yourself, or get better error responses from the server, or the error magically disappeared ;)