PFQueryTablViewController queryForTable method with network reachability

112 views Asked by At

I am trying to populate a PFQueryTableViewController with Question objects from my Parse backend. How do I implement blocks within this method?

- (PFQuery *)queryForTable  // I'm having issues with using the method "findObjectInBackgroundWithBlock" in this method.
{
    PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];

    [query fromLocalDatastore];
    [query orderByDescending:@"createdAt"];

    [query findObjectsInBackgroundWithBlock:^(NSArray *parseQuestions, NSError *error) { // Fetch from local datastore
        if (parseQuestions != nil) {
            NSMutableArray *mutableParseQuestions = [parseQuestions mutableCopy];
            self.questions = mutableParseQuestions;  // if Set local array to fetched Parse questions

        } else {

            if ([InternetReachabilityManager isReachable]) {

                [query findObjectsInBackgroundWithBlock:^(NSArray *parseQuestions, NSError *error) { // Fetch from Cloud
                      NSMutableArray *mutableParseQuestions = [parseQuestions mutableCopy];
                      self.questions = mutableParseQuestions;  // if Set local array to fetched Parse questions
                      [Question pinAllInBackground:parseQuestions];  // Save query results to local datastore

                }];
            }
        }
    }];

    return query;
}

When blocks are in this method I get this error. enter image description here

Is this because queryForTable is already a background process? Should I just use

[query findObjects]

Also, I'm trying to implement reachability into my fetch.

  1. Try fetching from local datastore
  2. Load data into table if they are there else switch to the network
  3. Call block if network is available
  4. Save the results of the network fetch into the local datastore

I know that this method is supposed to automatically assign objects it fetches to rows but I don't know how to work with it if we're passing around a PFObject subclass object. This is my explanation for the arrays.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    self.question = [self.questions objectAtIndex:indexPath.row]; // Save one question from row

    static NSString *identifier = @"QuestionsCell";

    QuestionsCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];

    if (cell == nil) {
        cell = [[QuestionsCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
    }

    [cell setQuestion:self.question];  //

    return cell;
}

This is how I use the fetched array to populate the tableView.

So my questions:

  1. Why can't I call a block inside of queryForTable?
  2. Is there any way I can make this simpler by using queryForTable's automatic assigning of objects to rows?
  3. If the internet is unreachable and the local datastore is empty what should I do?
1

There are 1 answers

4
AlexKoren On
  1. There is no reason to call your query in that function. You're supposed to create a query and then return it. PFQueryTableViewController does the actual handling of the request. Read the documentation here: https://parse.com/docs/ios/api/Classes/PFQueryTableViewController.html#//api/name/queryForTable

  2. Once you're in the cellForRowAtIndexPath method you can call objectAtIndexPath: which will you give you the object you need and then use the data from it to set up your cell.

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        PFObject *object = [self objectAtIndexPath:indexPath];
    
        UITableViewCell *cell = ....
    
        //configure cell using object here
    
        return cell;
    }
    
  3. You do this (semi-pseudo code)

    -(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section {
        if (self.objects.count == 0) {
            Put some sort of overlay that shows there are no objects to be retrieved or internet is unreachable.
        }
        return self.objects.count;
    }