Dhanunjaya
Dhanunjaya

Reputation: 500

Update labels in UITableViewCell from multiple threads

After getting the data from multiple device, I am reloading tableview but tableview is flashing the labels. For example, two rows are in tableview contains two labels each. When I call reload tableview, displaying data in first row and second row will be empty and when displaying second row, first row will be empty. Like that it is flashing please help me how can I solve this

like this I am reloading tableview

[devicesTableView performSelectorOnMainThread:@selector(reloadData)
                                   withObject:nil
                                waitUntilDone:NO];

This is CellForAtIndexPath Method:

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

   static NSString *simpleTableIdentifier = @"DeviceCustomTableViewCellIdentifier";

    devicesCustomTableViewCell = (DeviceCustomTableViewCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
    if (devicesCustomTableViewCell == nil)
    {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"DeviceCustomTableViewCell" owner:self options:nil];
        devicesCustomTableViewCell = [nib objectAtIndex:0];
    }

    DeviceDetails *deviceDetailsEntity = [devicesArray objectAtIndex:indexPath.row];

    devicesCustomTableViewCell.deviceName.text = deviceDetailsEntity.deviceLocalName;

    for (int i=0; i<[dataArray count]; i++) {
        DeviceParticulars *deviceParticulars = [dataArray objectAtIndex:i];
        if ([[[deviceParticulars.peripheral identifier] UUIDString] isEqualToString:deviceDetailsEntity.deviceAddress]) {

            devicesCustomTableViewCell.temperatureValueLabel.text = deviceParticulars.tempReadOutStr;



   }

In this, DeviceDetails class is core data class, In that I am saving BLE device name as per requirement.

DeviceParticulars class is NSObject class for saving data from multiple BLE devices like I am getting temperature from multiple devices. I am displaying Temp values in tableview.

dataArray is an array contains DeviceParticulars object.

Upvotes: 0

Views: 213

Answers (2)

Paulw11
Paulw11

Reputation: 114856

Reloading the entire table every time a peripheral value changes is expensive and, as you are seeing, has visual impacts.

You can change your custom cell to act as a delegate to your model object - DeviceParticulars

In your DeviceParticulars.h file, register the delegate property and protocol

@property (weak,nonatomic) id delegate;

@protocol DeviceParticularsDelegate
- (void)didUpdateDevice:(DeviceParticulars *)device;
@end

In your DeviceParticulars.m file, where you update readings, call

[self.delegate didUpdateDevice:self];

Then in your DeviceCustomTableViewCell.h, add <DeviceParticularsDelegate> to the class definition and add a property to store your deviceParticulars

@property (strong,nonatomic) DeviceParticulars *myDevice;

In the .m implement the delegate method

-(void)didUpdateDevice:(DeviceParticulars *)device {
   // Update cell labels as required
}

and implement prepareForReuse

- (void)prepareForReuse {
    self.myDevice.delegate=nil;  // Remove this cell as delegate for existing device;
}

Finally, set the delegate in your cellForRowAtIndexPath

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

   static NSString *simpleTableIdentifier = @"DeviceCustomTableViewCellIdentifier";

    devicesCustomTableViewCell = (DeviceCustomTableViewCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
    if (devicesCustomTableViewCell == nil)
    {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"DeviceCustomTableViewCell" owner:self options:nil];
        devicesCustomTableViewCell = [nib objectAtIndex:0];
    }

    DeviceDetails *deviceDetailsEntity = [devicesArray objectAtIndex:indexPath.row];

    devicesCustomTableViewCell.deviceName.text = deviceDetailsEntity.deviceLocalName;

    for (int i=0; i<[dataArray count]; i++) {
        DeviceParticulars *deviceParticulars = [dataArray objectAtIndex:i];
        if ([[[deviceParticulars.peripheral identifier] UUIDString] isEqualToString:deviceDetailsEntity.deviceAddress]) {

            deviceParticulars.delegate=deviceCustomTableViewCell;   //Set the delegate
            devicesCustomTableViewCell.myDevice=deviceDetails;      //Set device property

            devicesCustomTableViewCell.temperatureValueLabel.text = deviceParticulars.tempReadOutStr;


   }

Upvotes: 1

user1564913
user1564913

Reputation:

Try using the -dequeueReusableCellWithIdentifier:forIndexPath: method for iOS 6 and later. It will automatically instantiate a cell if there is no reusable one, so you don't have to check if cell==nil. Not sure what causes your problems but I think it's worth to try it. Please let me know if it helps.

Upvotes: 1

Related Questions