dequeueReusableCellWithIdentifier:记住单元格的状态
我已在表格单元格内嵌入水平表格视图(如脉冲读取器)。我得到的有趣的行为是 dequeueReusableCellWithIdentifier: 似乎正确记住了嵌入表视图的偏移量,而无需我执行任何操作。但是“记住”有两种方式
首先(预期)
我创建一个包含 100 个部分、每个部分 1 行的表格。每个单元格(每个部分)都有一个嵌入的表格视图,我强制将其包含 100 行和 1 个部分。当我滚动垂直表格视图时,单元格会被重用(通过查看 dequeueReusableCellWithIdentifier 之后的单元格的实例名称进行检查:
VerticalTableViewCell *cell = (VerticalTableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
如果我将第一个表格视图单元格的嵌入表格视图向右滚动,比如说 10.5 个单元格,当我在垂直表格视图中向下滚动几个单元格时,重用的表格单元格的嵌入表格视图偏移了这 10.5 个单元格,这是有道理的,单元格只是被重用了,我没有重置。假设重用的单元格是第 7 行,当我转到顶部时,如果我现在将第 7 行的嵌入表格视图(由于重用,这与第一行相同的嵌入表格视图)滑动到位置 20。嵌入表格视图的垂直表格视图(我最初已移至 10.5)现在为 20。同样,预期这些表格单元格是相同的
第二个(期望的,但是 。不知道它是如何工作的)
现在我填写了我的真实数据(而不是仅仅打印
[cell.textLabel setText:[NSString stringWithFormat: @"here: %d", indexPath.row]];
到单元格。
现在,突然间,我嵌入的表格视图确实记住它们在哪里。我再次确保单元格被重复使用(与上面的方法相同)。但这一次,当我滚动第一个嵌入式表格视图(到位置 10.5)并向下滚动到第七行时,第七行位于其起点。当我将第一行滚动回到视图中时,它就在我离开的位置。
这是使用 Xcode 4.2 和 iOS 5.0。 dequeueReusableCellWithIdentifier:
有什么聪明的做法吗?
在老派(iOS 5.0 之前)中,我会检查
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
}
一些逻辑来看看发生了什么,但有了 StoryBoards,这些就不再是必要的了。
这两个行为不同的示例项目有点大,但如果您想查看任何相关代码,请告诉我。
抱歉说得这么含糊,我只是想准确了解这些表视图的内存管理到底发生了什么。
所有连接均通过 IBOutlet 并在 StoryBoard 中进行。
谢谢!
第一个垂直表视图控制器
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//#warning Potentially incomplete method implementation.
// Return the number of sections.
return 100;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//#warning Incomplete method implementation.
// Return the number of rows in the section.
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"PlayerCell";
PlayerCell *cell = (PlayerCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
cell.games = [NSMutableArray arrayWithCapacity:1];
if(indexPath.section <40){
//[cell.textLabel setText:[NSString stringWithFormat:@"h343: %d", indexPath.section]];
}
CGAffineTransform rotateTable = CGAffineTransformMakeRotation(-M_PI_2);
cell.htv.transform = rotateTable;
cell.htv.frame = CGRectMake(0, 0, 320, 120);
return cell;
}
第一个水平表视图委托/数据源
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return 100;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
//UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UITableViewCell *cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
CGAffineTransform rotateImage = CGAffineTransformMakeRotation(M_PI_2);
cell.transform = rotateImage;
//[cell.myLabel setText:[NSString stringWithFormat:@"%d", indexPath.row]];
[cell.textLabel setText:[NSString stringWithFormat: @"here: %d", indexPath.row]];
return cell;
}
第二个垂直表视图控制器
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [self.leagues count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"VerticalTableViewCell";
VerticalTableViewCell *cell = (VerticalTableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSLog(@"Cell: %@ for index: %d", cell, indexPath.section);
cell.games = [self.leagues objectAtIndex:indexPath.section];
CGAffineTransform rotateTable = CGAffineTransformMakeRotation(-M_PI_2);
cell.horizontalTableView.transform = rotateTable;
cell.horizontalTableView.frame = CGRectMake(0, 0, 320, 120);
// Configure the cell...
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.section = indexPath.section;
return cell;
}
第二个水平表视图委托/数据源
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.games count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"HorizontalTableViewCell";
//UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
GameTableCell *cell = (GameTableCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
CGAffineTransform rotateImage = CGAffineTransformMakeRotation(M_PI_2);
cell.transform = rotateImage;
//[cell.myLabel setText:[NSString stringWithFormat:@"%d", indexPath.row]];
NSDictionary *game = [self.games objectAtIndex:indexPath.row];
[cell.homeTeamLogo setImage:[UIImage imageNamed:[NSString stringWithFormat:@"%@",[game objectForKey:@"LogoImage_HomeTeam"]]]];
[cell.visitingTeamLogo setImage:[UIImage imageNamed:[NSString stringWithFormat:@"%@",[game objectForKey:@"LogoImage_VisitingTeam"]]]];
[cell.homeTeamName setText:[NSString stringWithFormat:@"%@", [game objectForKey:@"AbbreviatedName_HomeTeam"]]];
[cell.visitingTeamName setText:[NSString stringWithFormat:@"%@", [game objectForKey:@"AbbreviatedName_VisitingTeam"]]];
NSDictionary *gameTime = [game objectForKey:@"GameTime"];
NSString *minutes = [NSString stringWithFormat:@"%@", [gameTime objectForKey:@"Minutes"]];
if([minutes length]==1){
minutes = @"00";
}
NSString *timeOfGame = [NSString stringWithFormat:@"%@:%@",[gameTime objectForKey:@"Hours"], minutes];
[cell.gameTime setText:timeOfGame];
return cell;
}
I've embedded horizontal table views inside of table cells (ala the Pulse Reader). The interesting behavior that I'm getting is that dequeueReusableCellWithIdentifier:
seems to be correctly remembering the offset of the embedded table views, without me doing anything. But there are two flavors to "remembering"
First (expected)
I create a table with 100 sections and 1 row per section. Each cell (each section) gets an embedded table view that I force to have 100 rows and 1 section. When I scroll the vertical table view, cells are reused (checked by looking at the instance names of the cells after dequeueReusableCellWithIdentifier:
VerticalTableViewCell *cell = (VerticalTableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
If I scroll the first table view cell's embedded table view to the right, say 10.5 cells, when I scroll down a couple cells in the vertical table view, the reused table cell has its embedded table view offset by those 10.5 cells. This makes sense, the cell was just reused and I didn't reset any offsets. Let's say that reused cell was the 7th row. If I now slide the 7th row's embedded table view (this is the same embedded table view as row one, due to the reuse) to position 20, when I go to the top of the vertical table view that embedded table view (which I had originally moved to 10.5), is now at 20. Again, expected, those table cells are the same. Just reused.
Second (desired, but have no idea how it works)
Now I fill in my real data (instead of just printing
[cell.textLabel setText:[NSString stringWithFormat: @"here: %d", indexPath.row]];
to the cell.
Now, all of a sudden, my embedded table views DO remember where they were. I once again ensure the cells are being reused (same method as above). But this time, when I scroll the first embedded table view (to position 10.5) and scroll down to the seventh row, the seventh row is at its starting point. When I scroll the first row back into view, it's right where I left it.
This is using Xcode 4.2 and iOS 5.0. Is there something smart that dequeueReusableCellWithIdentifier:
does?
In old school (pre-iOS 5.0), I would have checked the
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
}
bits of logic to see what was happening, but with StoryBoards those are no longer necessary.
The 2 sample projects that behave differently are kind of big, but if there's any relevant code you'd like to see, let me know.
Sorry to be so vague, I'm just trying to grasp exactly whats going on with the memory management of these table views.
All the connections are via IBOutlets and made in the StoryBoard.
Thanks!
First Vertical Table View Controller
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//#warning Potentially incomplete method implementation.
// Return the number of sections.
return 100;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//#warning Incomplete method implementation.
// Return the number of rows in the section.
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"PlayerCell";
PlayerCell *cell = (PlayerCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
cell.games = [NSMutableArray arrayWithCapacity:1];
if(indexPath.section <40){
//[cell.textLabel setText:[NSString stringWithFormat:@"h343: %d", indexPath.section]];
}
CGAffineTransform rotateTable = CGAffineTransformMakeRotation(-M_PI_2);
cell.htv.transform = rotateTable;
cell.htv.frame = CGRectMake(0, 0, 320, 120);
return cell;
}
First Horizontal Table View Delegate/Data Source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return 100;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
//UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UITableViewCell *cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
CGAffineTransform rotateImage = CGAffineTransformMakeRotation(M_PI_2);
cell.transform = rotateImage;
//[cell.myLabel setText:[NSString stringWithFormat:@"%d", indexPath.row]];
[cell.textLabel setText:[NSString stringWithFormat: @"here: %d", indexPath.row]];
return cell;
}
Second Vertical Table View Controller
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [self.leagues count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"VerticalTableViewCell";
VerticalTableViewCell *cell = (VerticalTableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSLog(@"Cell: %@ for index: %d", cell, indexPath.section);
cell.games = [self.leagues objectAtIndex:indexPath.section];
CGAffineTransform rotateTable = CGAffineTransformMakeRotation(-M_PI_2);
cell.horizontalTableView.transform = rotateTable;
cell.horizontalTableView.frame = CGRectMake(0, 0, 320, 120);
// Configure the cell...
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.section = indexPath.section;
return cell;
}
Second Horizontal Table View Delegate/Data Source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.games count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"HorizontalTableViewCell";
//UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
GameTableCell *cell = (GameTableCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
CGAffineTransform rotateImage = CGAffineTransformMakeRotation(M_PI_2);
cell.transform = rotateImage;
//[cell.myLabel setText:[NSString stringWithFormat:@"%d", indexPath.row]];
NSDictionary *game = [self.games objectAtIndex:indexPath.row];
[cell.homeTeamLogo setImage:[UIImage imageNamed:[NSString stringWithFormat:@"%@",[game objectForKey:@"LogoImage_HomeTeam"]]]];
[cell.visitingTeamLogo setImage:[UIImage imageNamed:[NSString stringWithFormat:@"%@",[game objectForKey:@"LogoImage_VisitingTeam"]]]];
[cell.homeTeamName setText:[NSString stringWithFormat:@"%@", [game objectForKey:@"AbbreviatedName_HomeTeam"]]];
[cell.visitingTeamName setText:[NSString stringWithFormat:@"%@", [game objectForKey:@"AbbreviatedName_VisitingTeam"]]];
NSDictionary *gameTime = [game objectForKey:@"GameTime"];
NSString *minutes = [NSString stringWithFormat:@"%@", [gameTime objectForKey:@"Minutes"]];
if([minutes length]==1){
minutes = @"00";
}
NSString *timeOfGame = [NSString stringWithFormat:@"%@:%@",[gameTime objectForKey:@"Hours"], minutes];
[cell.gameTime setText:timeOfGame];
return cell;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我的错。
我正在保存嵌入表视图的状态。
仅供参考:我正在使用 tableView.contentOffset (以防以后有人需要这样做)。
哎呀。
My fault.
I was saving the state of the the embedded Table View.
FYI: I was using the tableView.contentOffset (in case anybody needs to do this later).
Whoops.