Ragazzetto
Ragazzetto

Reputation: 642

How can I reload the data in a WatchKit tableview?

I have an app for iPhone with a Tableview, whose data comes from CoreData.

enter image description here

The same data are also displayed in a watch app:

enter image description here

If I add a row from the iPhone app:

enter image description here

and I reload data in the Watch app:

enter image description here

I see the old rows empty!

enter image description here

If the stop the watch app and I start it again, everything appears correctly!

enter image description here

This is the code to fill the Tableview in the watch app

-(void)awakeWithContext:(id)context{
    [super awakeWithContext:context];
       [self loadTable];
}

-(void)loadTable{
    NSLog(@"loadTableData");
    NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Data"];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Data"
        inManagedObjectContext:managedObjectContext];
    [fetchRequest setEntity:entity];

    NSSortDescriptor *sortByDate = [[NSSortDescriptor alloc] initWithKey:@"sortedDateAndTime" ascending:NO];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortByDate, nil];
    [fetchRequest setSortDescriptors:sortDescriptors];
    self.watchMArray = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];

  //  [self.watchTableView setRowTypes:self.watchMArray];
    [self.watchTableView setNumberOfRows:self.watchMArray.count withRowType:@"data"];

    for (NSInteger i = 0; i < self.watchMArray.count; i++)
    {
        WatchTableCell *cell = [self.watchTableView rowControllerAtIndex:i];
        NSManagedObject *data = [self.watchMArray objectAtIndex:i];
        dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
            //Background Thread
            UIImage *foto =[self loadImageFromData:[data valueForKey:@"imageData"]];
            dispatch_async(dispatch_get_main_queue(), ^(void){
                //Run UI Updates
            [cell.watchImage setImage:foto];
            [cell.watchDate setText:[NSString stringWithFormat:@"%@", [data valueForKey:@"dataEOra"] ]];
            });
        });
    }
}

This is the code I am currently using to reload it:

- (IBAction)reloadTable {        
    [self loadTable];
}

Where am I wrong?

Upvotes: 23

Views: 10720

Answers (6)

Andrei Marcu
Andrei Marcu

Reputation: 588

For watchOS 5.1, iOS 12.1 it only worked if I added the setNumberOfRows:withRowType: in didAppear method. Using the awake(withContext:) or willActivate did not work for me. The first 4 rows were blank.

Upvotes: 1

IsPha
IsPha

Reputation: 419

I do believe you have to do two things simultaneously in order to achieve same result of tableview.reloadData() iOS function , so to reload a table in the watch with newly data do the following : 1-call table method :setNumberOfRows 2-loop through the rows refreshing values .

vacationList.setNumberOfRows(dict.count, withRowType: "vacationRow")
    for index in 0..<vacationList.numberOfRows {
        if let controller = vacationList.rowControllerAtIndex(index) as? VacationRowcontroller {
            controller.vacation = dict.objectForKey("\(index)") as? NSDictionary
        }
    } 

hint : dict = dictionary of newly reloaded data from backend.

Upvotes: 0

Tap Forms
Tap Forms

Reputation: 911

I've discovered that calling setNumberOfRows:rowType does not refresh the table unless you call it from the willActivate method. I had a delegate method that I was calling from a modal controller which would fetch a new set of records from the parent app and then reload the table. Even though printing out numberOfRows showed the new number of rows that I set, visually the existing rows were still displayed on screen. It was only after I set a flag in my delegate method and then in willActivate checked that flag and only then reloaded the table, did it refresh the display.

Upvotes: 4

Bonan
Bonan

Reputation: 719

In the link @leolobato posted, there is actually a workaround. It did solve my problem.

https://devforums.apple.com/message/1098875#1098875

when you change your rows just set them to =@"" first.

For example, if your row has a row.Label and you are changing it, do row.Label.text = @"" then again right after row.Label.text =@"[Actual text]"

Upvotes: 11

Duncan Babbage
Duncan Babbage

Reputation: 20177

To reload the data, change your IBAction to:

- (IBAction)reloadTable {
    [self.watchTableView setNumberOfRows:self.watchMArray.count withRowType:@"data"];
}

From Apple's developer documentation on WKInterfaceTable:

This method removes any existing rows from the table and configures a new set of rows based on the information in the numberOfRows and rowType parameters.

Given you are using setNumberOfRows:withRowType: in your original code, I have used that here. The method setRowTypes: also achieves the same effect.

Upvotes: 1

Jay
Jay

Reputation: 864

Calling the setRowTypes: or setNumberOfRows:withRowType: method.

Below is a statement from the developer document, I believe this will work.

When you want to update the contents of a table, call setRowTypes: or setNumberOfRows:withRowType: again with the new row type information. Calling these methods again forces the table to discard the old rows and create new ones. To insert new rows without removing the old ones, use the insertRowsAtIndexes:withRowType: method.

Link to document

Upvotes: 6

Related Questions