从Storyboard加载uitableViewCell而不使用dequeueReusableCellWithIdentifier

时间:2013-12-03 21:14:57

标签: ios objective-c uitableview storyboard

我想从故事板加载tableViewCell而不使用dequeueReusableCellWithIdentifier来创建一个原型单元格,以便在调用cellForRowAtIndex之前引用。在CellForRowAtIndex之外调用它确实很有趣。 dequeueReusableCellWithIdentifier仍然正常用于cellForRowAtIndex。

我根据它的内容动态设置单元格高度。这需要我知道tableViewCell中视图的大小,位置,文本属性,如字体大小,对齐方式等。否则,我必须硬编码这些值以匹配故事板中的内容。

我目前正在做的是创建一个只包含单元格的新xib文件,从viewDidLoad加载它,并保留指向它的指针。

-(void)viewDidLoad {
    // typical coding stuff goes here 

    // load nib
    UINib *nib = [UINib nibWithNibName:@"ContentTextCell" bundle:nil];

    // assign nib to identifier
    [self.tableView registerNib:nib forCellReuseIdentifier:@"ContentTextCell"];

    // reference cell
    NSArray *topLevelObjects = [nib instantiateWithOwner:nil options:nil];
    _referenceContentTextCell = [topLevelObjects objectAtIndex:0];
}

有没有办法让我加载tableview单元而不使用自己的笔尖?使用dequeueReusableCellWithIdentifier:forIndexPath:会导致tableView以不正确的方式运行。

补充说明 我认为很多人都认为我在cellForRowAtIndex上调用了代码。它在viewDidLoad中调用。它总是这样显示,但也许在浏览问题时很容易理解。我还在cellForRowAtIndex中正常使用dequeueResuableCell。只是想说清楚。

行高是动态的。如果您提出我应该将行高设置为44,那么您可能需要在尝试回答问题之前更仔细地阅读问题。

我正在使用的文本来自json文件,它需要textView的段落,字体和位置来计算文本高度,这会影响行高。我想从原型单元中提取这些数据,而不是对值进行硬编码,并确保它们与故事板中的内容相匹配。

代码已经按原样运行。它运行正常。我只是觉得能够从故事板中拉出原型单元而不是为它制作新的xib更方便。

3 个答案:

答案 0 :(得分:1)

如果我理解正确,行高是模型的函数和单元格中子视图的一些属性,例如,模型中的字符串和单元格文本视图中的字体大小。

我同意将单元格的子视图的视图属性保留在代码中似乎是多余的,并且将它们保留在故事板中,但是保持参考单元格是很奇怪的。你是否从笔尖获取单元格或者是否找到了从故事板中获取单元格的方法(我认为你不能,这是你所陈述的问题的答案),这很奇怪。

将heightForRowAtIndexPath中的单元格排队更有意义,并且可能会导致无限递归循环,因为我确信您已经找到了。

所以你可能不会喜欢这个答案,但我认为最好的想法是“态度改变的冗余”。 “冗余”意味着您将视图属性保留在代码中,就像返回textView所需字体pointSize的方法一样。 “态度改变”,意味着你不认为这是冗余。相反,您的代码应该是与行高相关的所有视图属性的权限。将故事板中的原型单元视为可视化正确编码值的方式。我甚至建议在配置单元格时使用编码值在代码中设置属性,特别是如果没有太多的单元格。

最后,如果你的rowHeight计算很复杂,听起来像是这样,那么一定要实现

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath

并在其中进行更快速的计算(如返回常数)。

答案 1 :(得分:1)

我刚刚解决了几乎完全相同的问题。你想要高度,但高度取决于一堆单元格UI设置。检查图像上方和下方的填充高度甚至可能是一项相当简单的任务。在你完成之前可以在IB中多次调整的东西,所以你不想在代码中复制填充值,你想要根据IB中的当前值来检查它们。

您可以从任何地方拨打dequeueReusableCellWithIdentifier:(假设您有UITableView的引用)。因此,您不需要其他方式来获取单元格。这不会导致递归或无限循环问题。

虽然有一个问题。单元格不会返回自动重用池。 UITableView计算出哪些单元格从屏幕滚动并将它们放入池中,但是此单元格永远不会进入屏幕,因此表格视图永远不会将其从屏幕上移除并将其放回池中。更糟糕的是,该表仍然有很强的参考价值;所以,如果你失去你的参考,它不会被清理干净,它本质上是泄露的记忆。您无法使用它,表视图无法使用它,它将保留在内存中,直到后台UITableView被取消分配。

我找到了一些解决问题的方法:

  1. 将单元格出列一次,将其存放在安全的地方,并在每次需要测试一些单元格格式时使用相同的单元格。每次要测试新内容时,您甚至可以调用prepareForReuse:来清理它。在内存中保留一个额外的单元格不太可能成为大多数应用程序的杀手。
  2. 将其放回重用池中。等等,什么?是的,我说你做不到,但你可以,但这个想法让我有点畏缩。下次到达cellForRowAtIndexPath:时,不要将新单元格出列,请使用您放置的单元格,然后返回该单元格。这将使你任性的细胞回到折叠状态,最终会重新进入重用池。
  3. 所以你可以这样做....你呢?嗯,这是一个不同的问题。 Apple提供了一些替代方案来尝试解决这个问题,但在某些情况下,它们并没有有效地发挥作用。

答案 2 :(得分:0)

这是一个糟糕的模式,你会开始得到你已经看过的不受欢迎的行为。将height作为类方法存储在单元格中可能会更好。

+ (CGFloat)requiredHeight;
{ 
  return 44.f;
}

并将其称为

self.tableView.rowHeight = [OKACell requiredHeight];

这意味着你需要在两个地方管理高度,但由于描述性的名称和类方法,在那个时间到来时应该不难改变。