【问题标题】:reused UITableViewCell with KVO使用 KVO 重用 UITableViewCell
【发布时间】:2019-01-31 10:40:06
【问题描述】:

重用 UITableViewCell 的 tableview,每个单元格都有自己的 Label。这个标签是我定义的,UILabel 的一个子类。标签显示一个字符串。并且字符串的更改取决于 NSMutableDictionary。在标签类中,我使用 KVO 来添加观察者。当 NSMutableDictionary 中 key 的值发生变化时,标签会接收到这个变化并改变显示值。问题是当 NSMutableDictionary removeAllObjects。单元格中的大多数标签显示为“-.-”,没错。但是只有少数单元格的标签显示以前的值,这是不对的。好像是因为重用了tableviewcells,才会出现这个bug。

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) {

}

}

【问题讨论】:

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


    【解决方案1】:

    您说问题来自重复使用的单元是对的。

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

    要修复它,请在使用prepareForReuse 方法重用单元格时重置valueLabel.paramKey。将以下代码放入您的 ParameterTableViewCell 类中

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

    【讨论】:

    • 感谢您的热心回复,但这并不能解决我的问题。
    • 可以添加tableView:cellForRowAtIndexPath:方法吗?
    • 你有Skype账号吗?我可以和你签约吗?非常感谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-01
    • 1970-01-01
    • 2013-06-05
    • 1970-01-01
    • 2011-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多