Когда я закомментирую эту строку в моей cellForRowAtIndexPath:
функции:
cell = (tvcCustomCellWithSetter *)[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
.. тогда все ячейки регенерируются каждый раз и не используются повторно ... Это приводит к тому, что все текущие значения моей ячейки таблицы будут идеально установлены Однако мои ячейки должны отображать старые и новые значения. Конечно, поскольку ячейка всегда выделяется, все исторические значения теряются.
.. Когда я оставлю эту строку там и прокручиваю до конца моего табличного представления, значения в ячейках внизу таблицы будут содержать некоторые значения, которые принадлежат ячейкам вверху ... I ' мы что-то перепутали.
Короче, у меня есть UITableView
, составленный из пользовательских UITableViewCell
s. Пользовательские ячейки имеют следующее:
- и
UIStepper
контроль
- и
id delegate
для хранения вызывающего tableView
, чтобы я мог запускать методы в tableView
.
- свойства, которые позволяют каждой ячейке хранить свой раздел и строку в табличном представлении
Постановка задачи:
Когда я загружаю tableview
и пользователь касается элемента управления UIStepper
в ячейке, он вызывает функцию делегата doit:
, обратно в реализацию tableView
. В этой функции свойства секции и строки пользовательской ячейки работают отлично, и они идеально указывают на правую секцию и строку в источнике данных (и tableView
), но stepper.value
устанавливается «как-то» на stepper.value
из другая ячейка в таблице.
Кроме того, я действительно замечаю эту аномалию, только когда прокручиваю значительные расстояния в таблице ... т.е. сверху вниз. В нижней ячейке stepper.value
будет ячейка, которая находилась рядом с верхней частью таблицы. Поэтому я думаю, что столкнулся с осложнением, связанным с кэшированием ячеек и т. Д.
Я включил код из класса customCell, а также из родительского TableView.
Кто-нибудь видит ошибку в моих способах? Большое спасибо.
Вот заголовочный файл customTableViewCell
.
Возвращаясь к реальному TableView, где я создаю пользовательские ячейки, я вызываю метод setDelegate:
пользовательской ячейки (показан ниже), чтобы понять, какая ячейка в таблице была нажата.
«Звездой» шоу является элемент управления UIStepper, который позволяет пользователю «поднимать» или «опускать»
значение оценки, которое также отображается в ячейке.
#import <UIKit/UIKit.h>
@interface tvcCustomCellWithSetter : UITableViewCell {
id delegate;
NSNumber * row;
NSNumber * section;
int originalValueIsSet; }
@property (nonatomic, assign) IBOutlet UILabel *score; @property
(nonatomic, assign) IBOutlet UILabel *catAndWeight; @property
(nonatomic, assign) IBOutlet UILabel *orgValueText; @property
(nonatomic, assign) IBOutlet UILabel *orgValueValue; @property
(nonatomic, assign) IBOutlet UIStepper *theStepper; @property
(nonatomic, assign) id delegate; @property (nonatomic, assign)
NSNumber *row; @property (nonatomic, assign) NSNumber *section;
@property (nonatomic, assign) int originalValueIsSet;
- (IBAction) bumpTheScore;
- (id)delegate;
- (void)setDelegate:(id)newDelegate;
@end
Вот важная часть файла customTableViewCell .m:
//
// here is my IBACTION function associated with a touch event on the UISetter control
//
-(void) bumpTheScore {
[self.delegate doit:self];
}
- (id)delegate {
return delegate;
}
//
// this function is called when the cell is alloc'd over in the Tableview controller.
// it allows this custom cell to maintain a reference to the
- (void)setDelegate:(id)newDelegate {
delegate = newDelegate;
}
Вот TableView, в котором находятся объекты customViewCell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
tvcCustomCellWithSetter *cell = nil;
cell = (tvcCustomCellWithSetter *)[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"customCell" owner:self options:nil];
for(id currentObject in topLevelObjects){
if([currentObject isKindOfClass:[tvcCustomCellWithSetter class]]) {
cell = (tvcCustomCellWithSetter *)currentObject;
break;
}
}
}
// since the cell is a custom cell and it lives in a new class file, when events
// occur from toys in that cell (i.e. sliders, stepper, etc), the events go to that
// class file. I want those events to go to the simgrades class and run a reactive
// function in there. this is how you do that. see the two functions in the
// custom class that work with this line.
[cell setDelegate:self];
// similarly, save the current section and row into the custom cell itself
// so that later, when the stepper is clicked on one of the cells, we'll be able
// to know the location in the datasource that is being addressed by the user.
[cell setRow: [NSNumber numberWithInt: indexPath.row]];
[cell setSection: [NSNumber numberWithInt: indexPath.section]];
// Set up the cell...
[self.tableView setAllowsSelectionDuringEditing:NO];
SimCat *tmpCat = [simCatalog objectAtIndex: indexPath.section];
SimGrade *tmpGrd = [[tmpCat simGrades] objectAtIndex:indexPath.row];
float averageScore, _score, _total;
_score = [tmpGrd.scoreValue floatValue];
_total = [tmpGrd.scorePossible floatValue];
averageScore = (_score / _total) * 100;
// Configure the cell... Category name and description
if (tmpGrd.isSimGrade) {
cell.score.text = [NSString stringWithFormat:@"SimGrade: %2.2f%% - (%@ of %@)", averageScore, [tmpGrd.scoreValue stringValue] , [tmpGrd.scorePossible stringValue]];
//for simulation grades, null out the orgValue labels.
cell.orgValueValue.text = [NSString stringWithString: @""];
cell.orgValueText.text = [NSString stringWithString: @""];
} else {
cell.score.text = [NSString stringWithFormat:@"Actual: %2.2f%% - (%@ of %@)", averageScore, [tmpGrd.scoreValue stringValue] , [tmpGrd.scorePossible stringValue]];
//set the orig value label and turn on the boolean that shows that you've set this already.
if (! cell.originalValueIsSet ) {
cell.orgValueValue.text = [NSString stringWithFormat:@"%@", [tmpGrd.scoreValue stringValue]];
cell.orgValueText.text = [NSString stringWithString: @"Original Value:"];
cell.originalValueIsSet = true;
}
}
cell.catAndWeight.text = [NSString stringWithFormat:@"Category: %@, Wt: %d", tmpCat.catName, [[tmpCat catWeight] intValue]];
[cell.theStepper setValue:[tmpGrd.scoreValue floatValue]];
[cell.theStepper setMaximumValue:[tmpGrd.scorePossible floatValue]];
[cell.theStepper setMinimumValue:0];
return cell;
}
Вот где у меня проблема. См. Описание проблемы в приведенном ниже коде.
- (void) doit: (id) sender {
NSLog(@"it worked - i got back inside the tableview that houses the custom cells");
NSLog(@"the user touched the UISetter control on a cell in section: %d", [[(tvcCustomCellWithSetter *)sender section] intValue]);
NSLog(@"and that cell was in row: %d of that section", [[(tvcCustomCellWithSetter *)sender row] intValue]);
// find the right section and row in the tableview's data source
// point to the section indicated by the "section" passed in from the custom cell.
SimCat *cat = [simCatalog objectAtIndex:[[(tvcCustomCellWithSetter *)sender section] intValue] ];
// now point at the array item that corresponds to the "row" passed in from the custom cell
SimGrade *grade = [[cat simGrades] objectAtIndex:[[(tvcCustomCellWithSetter *)sender row] intValue]];
// now that we are pointing at the right array item in the tableview's datasource, update it's value to that of the UIStepper
// control's value.
// THE PROBLEM OCCURS IN THE FOLLOWING LINES. The before value that is printed out is perfect. So I know I am able to
// reference the correct value in the datasource that the user has just incremented or decremented with the UIStepper
// control. The "theStepper.value" should contain a number that is one more or one less than the previous value...
// HOWEVER, the value stored in theStepper.value is actually a value from one of the other cells in the table.
// I'm thinking that this has to do with the way the table cells are cached. I usually see this error when I scroll to the
// bottom of the tableview.
NSLog(@"before: %f", [[grade scoreValue] floatValue]);
grade.scoreValue = [NSNumber numberWithFloat: [[(tvcCustomCellWithSetter *)sender theStepper] value]];
NSLog(@"after: %f", [[grade scoreValue] floatValue]);
// you have changed some values in the Tableview's datasource so you should repaint the view.
[self loadHTMLHeader];
[[self tableView] reloadData];
return;
}