Search code examples
iosobjective-cafnetworkingnsdata

AFNetworking NSData - Incompatible block pointer types sending


I am trying to redo some code to use AFNetworking. I have this method below:

-(NSArray *)GetTableDataOfPhase:(NSString *)phase
{
    NSString *phaseRequestString = [NSString stringWithFormat:@"%@?jobNo=%@",kIP,phase];
    NSURL *JSONURL = [NSURL URLWithString:phaseRequestString];
    NSURLResponse* response = nil;
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:JSONURL];
            NSData* data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
        if(data == nil)
            return nil;
        NSError *myError;
        NSArray *tableArray = [[NSArray alloc]initWithArray:[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&myError]];



    return tableArray;
}

and right now I am trying to alter it so it still returns an array, I have tried doing this:

-(NSArray *)GetTableDataOfPhase:(NSString *)phase
{
    NSString *phaseRequestString = [NSString stringWithFormat:@"%@?jobNo=%@",kIP,phase];
    NSURL *JSONURL = [NSURL URLWithString:phaseRequestString];
    NSURLResponse* response = nil;
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:JSONURL];

    AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc] initWithRequest:request] autorelease];

    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {

        NSData* data = [NSURLConnection sendSynchronousRequest:responseObject returningResponse:&response error:nil];
        if(data == nil)
            return nil;
        NSError *myError;
        NSArray *tableArray = [[NSArray alloc]initWithArray:[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&myError]];

    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {


    }];

    [operation start];


    return tableArray;
}

but I got this error:

/Users/jamessuske/Documents/My Programs/SSiPad(Device Only)ios7/SchedulingiPadApplication/Classes/LHJSonData.m:168:46: Incompatible block pointer types sending 'void *(^)(AFHTTPRequestOperation *, id)' to parameter of type 'void (^)(AFHTTPRequestOperation *, id)'

and this warning:

/Users/jamessuske/Documents/My Programs/SSiPad(Device Only)ios7/SchedulingiPadApplication/Classes/LHJSonData.m:170:97: Sending 'NSURLResponse *const *' to parameter of type 'NSURLResponse **' discards qualifiers

This is how I am calling it:

- (void)GetRequest
{
    //refresh table view
    [dataSource.editedCellHolder removeAllObjects];
    [dataSource.cellHolder removeAllObjects];
    [dataSource.cellHolderDisplay removeAllObjects];


    NSArray *tableData = [dataSource.areaData GetTableDataOfPhase:[NSString stringWithFormat:@"%@%@",areaPickerSelectionString,unitPickerSelectionString]];

    if(tableData == nil)
        [self CustomAlert:@"Data was not recieved from the server, please check internet/VPN settings, Or contact Software Vendor for assistance."];
    [dataSource PopulateTableData:tableData];
    [indicatorView stopAnimating];
    [indicatorView removeFromSuperview];
    [loadingView removeFromSuperview];
    loadingView = nil;
    indicatorView =nil;
    [NSTimer scheduledTimerWithTimeInterval:0.2f target:self selector:@selector(DisplayTable) userInfo:nil repeats:NO];

}

Solution

  • A couple of things:

    1. Using AFNetworking, you should entirely lose the NSURLConnection request.

    2. Likewise, the default responseSerializer does the JSON parsing for you, so you can lose the NSJSONSerialization parsing. AFNetworking does all of that for you.

    3. Likewise, don't build URL parameters manually, but rather again let AFNetworking do that for you. By default, AFNetworking uses a requestSerializer that will build the request for you.

    4. Your old method ran synchronously, which is generally a bad idea. Instead, you should use asynchronous patterns (e.g. a completionHandler block).

    So, pulling all of this together, it probably looks like:

    - (void)getTableDataOfPhase:(NSString *)phase completionHandler:(void (^)(NSArray *resultsObject, NSError *error))completionHandler
    {
        AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
        NSDictionary *parameters = @{@"jobNo" : phase};
    
        [manager GET:kIP parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
            completionHandler(responseObject, nil);
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            completionHandler(nil, error);
        }];
    }
    

    And you'd call it like so:

    [self getTableDataOfPhase:@"..." completionHandler:^(NSArray *resultsObject, NSError *error) {
        if (resultsObject) {
            // use NSArray here
        } else {
            NSLog(@"error = %@", error);
        }
    }];
    
    // but don't try to use the `resultsObject` array here!