用KVO重用UITableViewCell

时间:2019-01-31 10:40:07

标签: ios objective-c uitableview key-value-observing

具有重用的UITableViewCell的表视图,每个单元格都有其自己的Label。我定义的这个Label是UILabel的子类。标签显示一个字符串。并根据NSMutableDictionary更改字符串。在标签类中,我使用KVO来添加对象服务器。当NSMutableDictionary中的键的值更改时,标签将接收此更改并更改显示值。问题在于NSMutableDictionary removeAllObjects。单元格中显示的大多数标签都带有“ -.-”,这是正确的。但是只有几个单元格的标签显示了先前的值,那是不对的。似乎由于tableviewcells的重用,发生了此错误。

Tableview Class:

//Add Observer

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
// Add Observer
   NSDictionary* dic = [_paramters objectAtIndex:indexPath.row];
   if (!dic || dic.count <= 0) {
     return;
   }

  NSString* key = [dic.allKeys objectAtIndex:0];
  if (!key || key.length <= 0) {
    return;
  }

   ParameterTableViewCell* paramCell = (ParameterTableViewCell*)cell;
   //Add Observer
   paramCell.valueLabel.paramKey = key;
}

// Remove Observer
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{

  ParameterTableViewCell* paramCell = (ParameterTableViewCell*)cell;
  //Remove Observer
  [paramCell.valueLabel removeKeyObserver:paramCell.valueLabel.paramKey];
}

Label Class
- (void)setParamKey:(NSString *)paramKey{
  if (![_paramKey isEqualToString:paramKey]) {
    [[CnogaCurveManager sharedCurveManager] addParameterValueObserver:self forParameterKey:paramKey];
    _paramKey = paramKey;
  }
}

- (void)removeKeyObserver:(NSString*)paramKey{
 [[CnogaCurveManager sharedCurveManager] removeParameterValueObserver:self forParameterKey:paramKey];
}

- (void)dealloc{
 [[CnogaCurveManager sharedCurveManager] removeParameterValueObserver:self forParameterKey:_paramKey];
}


//This is where I change label's value
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
                    change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
if([_paramKey isEqualToString:keyPath]){
    dispatch_async(dispatch_get_main_queue(), ^(){
        self.text = [[CnogaCurveManager sharedCurveManager] paramterValueForKey:keyPath];
        if (!self.text){
            self.text = @"-.-";
        }
    });
 }
}

CnogaCurveManager Class

- (void)addParameterValueObserver:(NSObject*)observer forParameterKey:(NSString*)parameterKey{
try {
    if(![NSString stringIsEmpty:parameterKey]){
        if ([self.obeseverKeys containsObject:parameterKey]) {
            return;
        }

        [self.parameterMeasurement addObserver:observer forKeyPath:parameterKey options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
        [self.obeseverKeys addObject:parameterKey];
       }
} catch (NSException *exception) {

}

}

- (void)removeParameterValueObserver:(NSObject*)observer forParameterKey:(NSString*)parameterKey{
try {
    if(![NSString stringIsEmpty:parameterKey]){
        if (![self.obeseverKeys containsObject:parameterKey]) {
            return;
        }

        [self.parameterMeasurement removeObserver:observer forKeyPath:parameterKey];
        [self.obeseverKeys removeObject:parameterKey];
    }
} catch (NSException *exception) {

}

}

1 个答案:

答案 0 :(得分:0)

您说的问题都来自重用小区时是正确的。

当您在removeAllObjects上调用dic时,key将是nil,它使tableView:willDisplayCell:返回,然后再次设置paramCell.valueLabel.paramKey。这就是为什么您看到一些单元格显示以前的值的原因。

要解决它,复位valueLabel.paramKey当小区是通过使用prepareForReuse方法重复使用。将下面的代码放在您的ParameterTableViewCell类中

- (void)prepareForReuse {
    [super prepareForReuse];
    self.valueLabel.paramKey = @"";
}