重用 UITableViewCell 与 KVO
reused UITableViewCell with KVO
重用 UITableViewCell 的表格视图,每个单元格都有自己的标签。这个Label是我定义的,UILabel的subclass。标签显示一个字符串。字符串的更改取决于 NSMutableDictionary。在标签 class 中,我正在使用 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) {
}
}
你说问题来自重复使用的电池是对的。
当您在 dic
上调用 removeAllObjects
时,key
将是 nil
并且它在设置 [=16 之前生成 tableView:willDisplayCell:
returns =] 再次。这就是为什么您会看到一些单元格显示以前的值。
要修复它,请在使用 prepareForReuse 方法重复使用单元格时重置 valueLabel.paramKey
。将下面的代码放入 ParameterTableViewCell
class
- (void)prepareForReuse {
[super prepareForReuse];
self.valueLabel.paramKey = @"";
}
重用 UITableViewCell 的表格视图,每个单元格都有自己的标签。这个Label是我定义的,UILabel的subclass。标签显示一个字符串。字符串的更改取决于 NSMutableDictionary。在标签 class 中,我正在使用 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) {
}
}
你说问题来自重复使用的电池是对的。
当您在 dic
上调用 removeAllObjects
时,key
将是 nil
并且它在设置 [=16 之前生成 tableView:willDisplayCell:
returns =] 再次。这就是为什么您会看到一些单元格显示以前的值。
要修复它,请在使用 prepareForReuse 方法重复使用单元格时重置 valueLabel.paramKey
。将下面的代码放入 ParameterTableViewCell
class
- (void)prepareForReuse {
[super prepareForReuse];
self.valueLabel.paramKey = @"";
}