Question

Here is how things are looking:

enter image description here

My root controller is a UITabBarController. Number 13 in the image is my default view that I've set to show a list of people when the app is first opened up.

Number 4 shows a page I'm taken to by clicking a settings link on page 3. On page 4 I can manage the people on the main view by confirming pending people or taking confirmed people offline. Basically I can set whether they show up or not or delete if I wish.

Changes are always shown in 5 and 6 because I remove rows after after deletions, confirmations or status changes. When making edits in the detail views 7 the changes are updated easily because I update the Person object that has been passed over during segue. So when I go back to the table view in 5 I just "self.tableView reloadData" in my viewWillLoad method.

In table 6 and action sheet pops up when I tap on a row and gives me the option to take any currently confirmed person back offline. All I do is remove the row and that's it. ViewDidLoad is run when ever I go back to controller view 4 then click "pending" or "confirmed".

Now the issue

Unlike my controller in number 4 my main table in number 13 is shown when my first UITableViewController tab is tapped or when the app is first loaded up. My code below is loaded in the viewDidLoad method and therefore only loaded once.

This is how my data is shown on main view:

- (void)populatePeopleArrayWithCloudData {
    // Grab data and store in Person instances and then store each person in array

    people = [[NSMutableArray alloc] init];

    PFQuery *query = [PFQuery queryWithClassName:@"People"];
    [query whereKey:@"active" equalTo:@1];
    [query orderByDescending:@"createdAt"];
    [query setLimit:10];
    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {

        if (!error) {
            for (PFObject *object in objects) {

                Person *person = [[Person alloc] init];
                [person setName:[object objectForKey:@"name"]];
                [person setNotes:[object objectForKey:@"notes"]];
                [person setAge:[[object objectForKey:@"age"] intValue]];
                [person setSince:[object objectForKey:@"since"]];
                [person setFrom:[object objectForKey:@"from"]];
                [person setReferenceNumber:[object objectForKey:@"referenceNumber"]];

                PFFile *userImageFile = object[@"image"];
                [userImageFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
                    if (!error) {
                        UIImage *image = [UIImage imageWithData:imageData];
                        [person setImage:image];
                    }
                }];

                [person setActive:[[object objectForKey:@"active"] intValue]];
                [person setObjectId:[object objectId]];
                [people addObject:person];
            }

        } else {
            // Log details of the failure
            NSLog(@"Error: %@ %@", error, [error userInfo]);
        }

        NSLog(@"Calling reloadData on %@ in viewDidLoad", self.tableView);
        [self.tableView reloadData]; 
    }];
}

The code grabs my data from parse, runs a for loop storing each person in a Person instance and adding it to an NSMutableArray instance "people". This people instance is accessed by my tableview datasource methods.

When I tap another tab and then tap my main tab again, viewDidLoad is not loaded again. Ok, that's understandable. Now what if I want my main table(13) to reflect changes made in tables 5 and 6? I thought I could just go to viewWillAppear and run "self.tableView reloadData". I did this and nothing happened. Well that's what I thought. After some messing around I realised that my "people" array wasn't updated with the latest data from my database.

I then decided to try and call my populatePeopleArrayWithCloudData method from viewWillAppear but this just causes duplicate entries. My people array is used to populate table 13 twice. I said ok let me take the populatePeopleArrayWithCloudData method out of viewDidLoad. This works and changes are shown but then I start having issues with images being loaded, showing up late , last row issues etc. Calling populatePeopleArrayWithCloudData method in viewDidLoad solves all those issues.

I like having the code in viewDidLoad because it means less calls to the database. Like when a user clicks on a row and it takes them to the detail views 14 and 15 and return back to 13 no calls are made to the database like they are when code is in viewWillAppear.

So I'm wondering if the best way to solve this issue I'm having to, is to some how update the "people" instance from tableView 6 (as soon as "take offline is click") and in tableview 5 (as soon as "publish" is clicked to confirm a person). Publishing a user sets active status to 1. Objects with a status of 1 are included in the query result above and therefore shown in the main tableview list. Taking a person offline sets their active status to 0 meaning they don't show up in the main list.

1. Would it be good/right to access the "people" instance from my table views 5 and 6 then update that people array appropriately? Maybe after the update have a method similar to populatePeopleArrayWithCloudData that repopulates people. Then in viewWillAppear I just reload the table again hoping it detects the new people instance and uses that.

2. If so how do I do this? Can you show a clear example if possible...

3. If not what way would you suggest I do this and can you show a clear example.

Thanks for your time Kind regards.

Was it helpful?

Solution

There are several approaches you can take for this but (assuming I understand your problem) I think that the best is to have a shared instance of your array of people. What you do is create an NSObject called ManyPeople and add the following:

ManyPeople.h:

 @property (nonatomic, strong) NSMutableArray *manyPeople;

 +(ManyPeople *) sharedInstance;

ManyPeople.m

+ (ManyPeople *) sharedInstance
 {
if (!_sharedInstance)
{
    _sharedInstance = [[ManyPeople alloc] init];
}

return _sharedInstance;
}

Now all your UIViewControllers can call ManyPeople *people = [ManyPeople sharedInstance]; and will get the same array. When make a call to the database you populate the shared instance. When you make changes to the settings you also make changes to the shared instance. The beauty is that when you return to your view controller 13 all you do is reloadData and you don't need to make a call to the database. The data source is already points to the updated array.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top