为啥将“viewWithTag”与“dequeueReusableCellWithIdentifier”一起使用?
Posted
技术标签:
【中文标题】为啥将“viewWithTag”与“dequeueReusableCellWithIdentifier”一起使用?【英文标题】:Why use "viewWithTag" with "dequeueReusableCellWithIdentifier"?为什么将“viewWithTag”与“dequeueReusableCellWithIdentifier”一起使用? 【发布时间】:2010-09-03 02:22:48 【问题描述】:有人能解释一下为什么你应该使用viewWithTag
从dequeueReusableCellWithIdentifier
的单元格中获取子视图(例如UILabel
等)吗?
一些背景信息:我有一个自定义的UITableViewCell
,里面有几个UILabel
s(我在下面复制了一个简单的版本)。这些标签在关联的 NIB 文件中定义,并使用 IBOutlet
s 声明并链接回自定义单元的控制器类。在tableview的dequeueReusableCellWithIdentifier
中,我正在这样做:
CustomCell *customCell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:@"CustomCellId"];
if (customCell == nil)
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"customCell" owner:self options:nil];
for (id oneObject in nib)
if ([oneObject isKindOfClass:[CustomCell class]])
customCell = (CustomCell *)oneObject;
customCell.firstLabel.text = @"Hello";
customCell.secondLabel.text = @"World!";
return customCell;
一切正常。但是,从我看到的教程来看,在更改标签的值时,我应该这样做:
UILabel *firstLabel = (UILabel *)[customCell.contentView viewWithTag:555];
firstLabel.text = @"Hello";
UILabel *secondLabel = (UILabel *)[customCell.contentView viewWithTag:556];
secondLabel.text = @"World!";
(标签的标签值已在NIB中设置)。
谁能告诉我首选哪种方法以及为什么?
谢谢!
【问题讨论】:
【参考方案1】:viewWithTag:
只是一种快速而肮脏的方式来拉出子视图,而无需在父视图上设置 IBOutlet 属性,甚至不必创建 UITableViewCell 子类。
对于非常简单的情况,这是一个可以接受的解决方案,这就是viewWithTag:
的目的。但是,如果您要多次重用该单元格,或者您希望它具有对开发人员更友好的界面,那么您将需要像第一个示例中那样子类化并使用真实属性。
所以使用viewWithTag:
如果它是您在 IB 中设计的一个非常简单的单元格,没有子类并且只有几个标签。将具有真实属性的单元子类用于更重要的内容。
【讨论】:
【参考方案2】:我已经意识到,如果元素以编程方式添加到单元格(即未在 NIB 中定义并通过 IBOutlets 连接),则使用“viewWithTag”检索元素很有用 - 这可以防止创建多个标签等对于单元格的每个实例。
【讨论】:
通常你应该使用 UITableViewCell 子类而不是快速而肮脏的 viewWithTag 方法。【参考方案3】:对我来说,viewWithTag 是上帝赐予的。首先:像 taskinoor 所说的那样在循环中处理所有视图真的很容易。另外,我个人更喜欢这种方式,因为如果我查看代码并想看看视图发生了什么,我只需搜索标签。它在处理视图的任何地方都使用。与您必须查看代码和 xib 的 xib 方法相反。此外,如果您在 xib 中有屏幕外视图,您可能会监督它。 我发现很多其他程序员制作的 xibs 都充满了很多很多的观点。一些隐藏的,一些屏幕外的,无法分辨哪个是哪个,因为它们都是重叠的。 在这些情况下,我认为 xib 很糟糕。它们不再易于阅读。 我更喜欢用代码制作的一切。
但如果您决定使用标签,请记住避免对任何标签进行硬编码。而是制作一个#define 定义列表,以保持代码简洁易读。
【讨论】:
【参考方案4】:我总是通过 IBOutlets 将子视图与我的 UITableViewCell 子类的属性挂钩,就像您所做的那样。我想不出任何使用 viewWithTag 的充分理由。
【讨论】:
【参考方案5】:来自 UITableViewCell 类参考:“tableView:cellForRowAtIndexPath 中的表格视图委托:在重用单元格时应始终重置所有内容。”保持简单,清除内容视图。这对自定义单元类没有任何假设,没有强制转换,没有类检查:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (cell != nil)
NSArray* contentSubViews = [cell.contentView subviews];
for (UIView* viewToRemove in contentSubViews)
[viewToRemove removeFromSuperview];
【讨论】:
【参考方案6】:viewWithTag:
允许样式无需创建UITableViewCell
的自定义子类。
您可以在 Interface Builder 中为原型 UITableViewCell
分配标签和重用标识符,然后在 UITableViewController
的实现中使用该标签出列并修改视图,而无需为该单元创建自定义类或创建 IBOutlets用于单元格的子视图。
在某些情况下,单元格的简单性让自定义类感觉有点矫枉过正。 viewWithTag:
允许您将自定义文本和图像添加到情节提要中的单元格,然后通过代码设置这些自定义项,而无需向您的 Xcode 项目添加额外的类文件。
【讨论】:
以上是关于为啥将“viewWithTag”与“dequeueReusableCellWithIdentifier”一起使用?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我不能使用 StoryBoard 从 viewWithTag 方法访问嵌套的 UIView?
OpenCV - 为啥光流不适用于 dequeue<Mat>?