当我在cellForRowAtIndexPath:
函数中注释掉这一行时:
cell = (tvcCustomCellWithSetter *)[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
..然后每次都重新生成所有单元格而不重复使用...这会导致我的所有tableview单元格当前值都被完美设置。但是,我的单元格需要显示旧值和新值。当然,由于单元格总是被分配,所以所有的历史值都会丢失。
..当我在那里留下那一行,并滚动到我的tableview的底部时,表格底部的单元格中的值将包含属于顶部单元格的一些值...我我得到了一些混乱的东西。
简而言之,我有UITableView
由自定义UITableViewCell
组成。自定义单元格具有以下内容:
UIStepper
控件id delegate
存储调用tableView
,以便我可以在tableView
中运行方法。问题陈述:
当我加载tableview
并且用户点击单元格中的UIStepper
控件时,它会在doit:
实现中调用委托函数tableView
。在该函数中,自定义单元格的节和行属性运行良好,它们完美地指向数据源中的右侧部分和行(以及tableView
),但stepper.value
被设置为“某种方式”到来自表格中另一个单元格的stepper.value
。
另外,当我在表格中滚动很长的距离时,我才真正注意到这种异常...即。从上到下。底部单元格的stepper.value
将是靠近表格顶部的单元格的customTableViewCell
。所以我认为我遇到了一个源于细胞缓存方式的并发症等等......
我已经包含了来自customCell类以及父TableView的代码。
有没有人以我的方式看到错误?非常感谢。
这是setDelegate:
头文件。
回到实际的TableView,我实例化自定义单元格,我调用自定义单元格的#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
方法(如下所示),以便能够理解表格中的哪个单元格被点击。
该节目的“明星”是UIStepper控件,允许用户“向上”或“向下” 得分值,也显示在单元格上。
//
// 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;
}
以下是customTableViewCell .m文件的重要部分:
- (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;
}
这是包含customViewCell对象的TableView。
- (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;
}
这是我遇到问题的地方。请参阅以下代码中的问题说明。
{{1}}
答案 0 :(得分:0)
要防止theStepper
值继续存在,如果dequeueReusableCell..
方法返回一个单元格,则需要将它们显式设置为默认值。
所以:
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;
}
}
} else {
cell.theStepper.value = 0;
cell.theStepper.maximumValue = 1;
// cell.theStepper.minimumValue = 0; this should already be set properly
}
一旦你这样做,那么你可以做进一步的调试,看看你的值是否没有正确设置(如果值为零,否则,你知道它没有为那个特定的单元格设置正确的值,然后在代码中放置断点并查看变量值等。)
编辑:我会更具体。从调试开始,您将逐步查看代码:
然后:
nil
,0
或者只是没有执行代码来设置值,您需要跟踪并查看代码到达该阶段的位置。)这应该是您的标准调试程序。
答案 1 :(得分:0)
我最后通过击败墙壁并继承UIStepper类来解决这个问题,以便添加一个行和节属性,使我能够确定在单击时呈现控件的是哪个tableview单元格。我还使用了一个“setTarget”方法,在cellforrowatindexpath()方法中放置在每个单元格上,只要在UIStepper上更改了值,它就会调用我的tableview类中的函数。在该函数中,我能够利用customStepper中的行和节值来精确定位表中的行,从而确定需要更新的数据源。
呼。