0

I have a UITableView and I'm attempting to get the number of rows. However, I'm having trouble using blocks. In the code below I'd just like to return count, but as I now understand blocks are asynchronous. I've looked around trying to find a solution but none of them worked. One solution I tried was this: How do I wait for an asynchronously dispatched block to finish? but when I clicked on the button to go to the view with the table, it just froze when the button was clicked. I tried some others, but they also did not work.

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
  GlobalVars *globals = [GlobalVars sharedInstance];

  __block int count = 0;
  GKLocalPlayer *localPlayer = [[GameCenterHelper sharedInstance] getLocalPlayer];
  [[GameCenterHelper sharedInstance] getMatches:^(NSArray *matches) {
    NSLog(@"Matches: %@", matches);
    for (GKTurnBasedMatch *match in matches) {
      for (GKTurnBasedParticipant *participant in match.participants) {
        if ([participant.playerID isEqualToString:localPlayer.playerID]) {
          if (participant.status == GKTurnBasedParticipantStatusInvited) {
            [globals.matchesReceived addObject:match];
            count++;
            NSLog(@"INVITED");
          }
        }
      }
    }
  }];

  return count;
}

Could someone help me properly get count returned?

Community
  • 1
  • 1
Jon
  • 319
  • 1
  • 4
  • 19
  • Your data should be already fetched at the point were you table view call numberOfRowsInSection since call blocks UI thread and may cause lag. Consider drawing spinner while you fetching the data and calling [tableView reloadData]; once load completed. You can fetch data into the array and later take count from arrays items count. – Keenle Jul 21 '14 at 16:58
  • _Blocks_ aren't asynchronous, the `getMatches:` method is asynchronous. – jscs Jul 21 '14 at 19:03

1 Answers1

1

You should be using callback blocks. Don't try to make asynchronous code behave synchronously.

Also, there's no need to have your GlobalVars singleton hold onto the array of matches. It could be considered bad design.

typedef void(^CallbackBlock)(id value);

- (void)viewDidLoad {
    [super viewDidLoad];
    //show some sort of loading "spinner" here
    [self loadMatchesWithCallback:(NSArray *matches) {
        //dismiss the loading "spinner" here
        self.matches = matches;
        [self.tableView reloadData];
    }];
}

- (void)loadMatchesWithCallback:(CallbackBlock)callback {
    GlobalVars *globals = [GlobalVars sharedInstance];
    GKLocalPlayer *localPlayer = [[GameCenterHelper sharedInstance] getLocalPlayer];
    [[GameCenterHelper sharedInstance] getMatches:^(NSArray *matches) {
        NSLog(@"Matches: %@", matches);
        NSMutableArray *filteredMatches = [NSMutableArray array];
        for (GKTurnBasedMatch *match in matches) {
            for (GKTurnBasedParticipant *participant in match.participants) {
                if ([participant.playerID isEqualToString:localPlayer.playerID]) {
                    if (participant.status == GKTurnBasedParticipantStatusInvited) {
                        [filteredMatches addObject:match];
                        break; //you don't want to add multiples of the same match do you?
                    }
                }
            }
        }
        if (callback) callback(filteredMatches);
    }];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.matches.count;
}
CrimsonChris
  • 4,651
  • 2
  • 19
  • 30