使用 KVO 重用 UITableViewCell
Posted
技术标签:
【中文标题】使用 KVO 重用 UITableViewCell【英文标题】:reused UITableViewCell with KVO 【发布时间】: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)
【问题讨论】:
【参考方案1】:您说问题来自重复使用的单元是对的。
当你在dic
上调用removeAllObjects
时,key
将是nil
并且它使tableView:willDisplayCell:
在再次设置paramCell.valueLabel.paramKey
之前返回。这就是为什么您会看到一些单元格显示以前的值。
要修复它,请在使用prepareForReuse 方法重用单元格时重置valueLabel.paramKey
。将以下代码放入您的 ParameterTableViewCell
类中
- (void)prepareForReuse
[super prepareForReuse];
self.valueLabel.paramKey = @"";
【讨论】:
感谢您的热心回复,但这并不能解决我的问题。 可以添加tableView:cellForRowAtIndexPath:方法吗? 你有Skype账号吗?我可以和你签约吗?非常感谢以上是关于使用 KVO 重用 UITableViewCell的主要内容,如果未能解决你的问题,请参考以下文章
如果文本为空,UITableViewCell detailTextLabel 不支持 KVO?苹果漏洞?