user3736412
user3736412

Reputation: 3

Using sendAsynchronousRequest:queue:completionHandler: for URL request

I'm working on an update of an iOS app that another developer created. He was using ASIHTTPRequest to handle http requests. However, the version of the app I have to work with crashes. Since ASIHTTPRequest is not being updated anymore, I thought then that I should switch to using AFNetworking, but it's far too complicated for me to figure out.

So finally I thought I could just use NSURLConnection on its own.

Here is the original code that I'm trying to replace:

-(NSArray*)readUTF16LEFeed:(NSURL*) urlToRead{
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:urlToRead];
    [request startSynchronous];
    NSError *error = [request error];
    if (!error) {
        lastModified = [NSDate date];
        NSData *response = [request responseData];//UTF-16LE
        NSString* responseString = [[NSString alloc] initWithData:response encoding:NSUTF16LittleEndianStringEncoding];
        DLog(@"string is: %@",responseString);
        responseString = [responseString stringByReplacingOccurrencesOfString:@"ISO-8859-1" withString:@"UTF16-LE"];
        NSData* data = [responseString dataUsingEncoding:NSUTF16LittleEndianStringEncoding];
        return [self parseNamesFromXML:data];
    }
    return nil;
}

And here is what I'm trying to use instead:

-(NSArray*)readUTF16LEFeed:(NSURL*) urlToRead{

    NSURLRequest *request = [NSURLRequest requestWithURL:urlToRead];
    [NSURLConnection sendAsynchronousRequest:request
                                       queue:[NSOperationQueue mainQueue]
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *error ) {

                               if ([data length] >0 && error == nil)
                               {
                                   // DO YOUR WORK HERE
                                   lastModified = [NSDate date];

                                   //   NSData *response = [request responseData];//UTF-16LE
                                   NSString* responseString = [[NSString alloc] initWithData:data encoding: NSUTF16LittleEndianStringEncoding];
                                   DLog(@"string is: %@",responseString);
                                   responseString = [responseString stringByReplacingOccurrencesOfString:@"ISO-8859-1" withString:@"UTF16-LE"];
                                   NSData* data = [responseString dataUsingEncoding:NSUTF16LittleEndianStringEncoding];
                                   return [self parseNamesFromXML:data];
                               }

                               else if ([data length] == 0 && error == nil)
                               {
                                   NSLog(@"Nothing was downloaded.");
                               }
                               else if (error != nil){
                                   NSLog(@"Error = %@", error);
                               }
                           }];
    return nil;
}

However, I'm getting the error "Incompatible block pointer types sending NSArray to parameter of type void. And also "Control may reach end of non-void block."

How can I get this to work?

Upvotes: 0

Views: 1493

Answers (2)

Naga Mallesh Maddali
Naga Mallesh Maddali

Reputation: 1005

Make return type of your method as void. Dont return anything. Just call [self parseNamesFromXML:data]; method.

-(void)readUTF16LEFeed:(NSURL*) urlToRead{


NSURLRequest *request = [NSURLRequest requestWithURL:urlToRead];
[NSURLConnection sendAsynchronousRequest:request
                                   queue:[NSOperationQueue mainQueue]
                       completionHandler:^(NSURLResponse *response, NSData *data, NSError *error ) {

                       if ([data length] >0 && error == nil)
                       {

                           // DO YOUR WORK HERE
                           lastModified = [NSDate date];

                      //   NSData *response = [request responseData];//UTF-16LE
                           NSString* responseString = [[NSString alloc] initWithData:data encoding: NSUTF16LittleEndianStringEncoding];
                           DLog(@"string is: %@",responseString);
                           responseString = [responseString stringByReplacingOccurrencesOfString:@"ISO-8859-1" withString:@"UTF16-LE"];
                           NSData* data = [responseString dataUsingEncoding:NSUTF16LittleEndianStringEncoding];
                           [self parseNamesFromXML:data];
                       }


                       else if ([data length] == 0 && error == nil)
                       {
                           NSLog(@"Nothing was downloaded.");
                       }
                       else if (error != nil){
                           NSLog(@"Error = %@", error);
                       }

                   }];
}

In parseNamesFromXML method, process your results and assign results array to a property. You can access it where ever you want.

-(void) parseNamesFromXML:(NSData *)xmlData
{     
    NSError *error;          
    //DLog(@"data is %@", [[NSString alloc] initWithData:xmlData encoding:NSUTF8StringEncoding ]);     

    GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData                                                            options:0 error:&error];          

    if (doc)
    {         
        self.dataArray = [self parseXmlDoc:doc]; 
    }              
}

Upvotes: 1

Florian
Florian

Reputation: 501

The completion block is called asynchronously, so by the time your code reaches return [self parseNamesFromXML:data]; the methods scope is already done (meaning the method returned nil.

Try using [NSURLConnection sendSynchronousRequest:returningResponse:error:] instead, since the original code is also synchronous.

Edit: As Julian Król suggested, if you return something within a block, it will be counted as the return value of this block, not of the original method. But since the block does not have a return value, you'll get the compiler error.

Upvotes: 0

Related Questions