質問

I got a async problem with my code. I got all of my webrequests in 1 class. One of my requests needs to return an NSMutableArray that another class needs to use. My webRequest code is here:

- (NSMutableArray*) getTournamentsInClub:(NSString *)clubGUID withDelegateViewController:(UIViewController *)viewController {

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSMutableArray *responseArray = [[[NSMutableArray alloc] init] autorelease];
NSString *URL = [[NSString alloc]initWithFormat:@"SomeURL=%@",clubGUID];
[manager POST:URL parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {

    for (id obj in responseObject){
        //NSLog(@"obj: %@",[obj valueForKey:@"CustomerName"]);
        [responseArray addObject:obj];
    }

} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"Error: %@", error);
}];
return responseArray;
}

I call the method from a viewController like this:

[self handleClubTournaments:[[TournamentsWebService sharedToursWS] getTournamentsInClub:

//Show load screen. (hide in handler function)
GP_MobilAppDelegate *xdelegate = [[UIApplication sharedApplication] delegate];
[xdelegate showLoadingScreen:self.clubToursTableView andStatus:NSLocalizedString(@"loadTours", @"")];

And my handleClubTournaments function looks like this:

-(void) handleClubTournaments:(id)result {

GP_MobilAppDelegate *xdelegate = [[UIApplication sharedApplication] delegate];

if([result isKindOfClass: [NSError class]]) {
    // If an error has occurred, handle it
    [xdelegate hideLoadingScreen];
    [[TournamentsWebService sharedToursWS] showErrorMessageAccordingToFault:result];
    return;
}

if([result isKindOfClass: [SoapFault class]]) {
    [xdelegate hideLoadingScreen];
    // If a server error has occurred, handle it
    [[TournamentsWebService sharedToursWS] showErrorMessageAccordingToFault:result];
    return;
}

//Do something with result...

if ([result count] > 0) {

    NSLog(@"Antal klubturneringer: %d", [result count]);
    //Start by removing excisting tours
    [self.tournamentsSourceArray removeAllObjects];
    NSMutableArray *tempArray=[NSMutableArray array];

    for (GGTournamentData *t in result) { //cast object in result list and add them to array

        [tempArray addObject:t];

    }
    self.tournamentsSourceArray = [self sortByStringDate:tempArray]; //sort by date

    [tempArray release];

    NSLog(NSLocalizedString(@"tourLoadet", @""));
}

[self.clubToursTableView reloadData];
[xdelegate hideLoadingScreen];

//Scroll view
if (self.tournamentsSourceArray.count > 0) { //hvis det er turneringer..
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:[self findIndexOfMonthClosestToDate]];
    [self.clubToursTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
}

So my problem is that the NSMutableArray gets returned before my async task is done. I know a async task behaves like that, but how do i make sure that my handleClubTournaments function don't run before my webrequest(getTournamentsInClub) got some data for it?

Thanks in advance.

役に立ちましたか?

解決

I don't think you know how Asynchronous operations work. The NSMutableArray will never be set, because it is returned synchronously. In your case, I suggest you to work with delegates.

- (void)getTournamentsInClub:(NSString *)clubGUID withDelegateViewController:(UIViewController *)viewController completionBlock:(void (^)(NSMutableArray *result))completionBlock {
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    NSMutableArray *responseArray = [[[NSMutableArray alloc] init] autorelease];
    NSString *URL = [[NSString alloc]initWithFormat:@"SomeURL=%@",clubGUID];
    [manager POST:URL parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {

        for (id obj in responseObject) {
            [responseArray addObject:obj];
        }

        // Request finished. Call the block.
        completionBlock(responseArray);

    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Error: %@", error);
    }];
}

- (void)handleClubTournaments {
    GP_MobilAppDelegate *xdelegate = [[UIApplication sharedApplication] delegate];
    [[TournamentsWebService sharedToursWS] getTournamentsInClub:^(NSMutableArray *result) 
    {
         // Hide the Loading Indicator. Do something with the Result.
    }];

    // You can't access the result synchronously, therefore it's impossible to depend on it synchronously.
}

another way to return the data asynchronously would be blocks, similar to the AFNetworking solution.

You can read more about getting started with blocks here and how to use delegates here.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top