我目前正在做一个项目,我在 UITableViewCell 中嵌入了一个 UITableView。
我需要做的是禁用 UITableView 的滚动并使 UITableView 适合所有行的大小。但由于 UITableView 继承自 UIScrollView,使用 Autolayout 不会强制 UITableView 使单元格的高度取决于返回 UITableViewAutomaticDimension 时的 contentSize(不是框架)。
在 iOS 7 之前,这是很容易实现的,因为我使用下面的代码获取了 heightForRowAtIndexPath: 下单元格的引用:
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
int height = cell.tableView.contentSize.height;
return height;
但在 iOS 8 中,它给出了 BAD_ACCESS,因为 iOS 8 在调用 cellForRowAtIndexPath: 之前调用了 heightForRowAtIndexPath:。
声明一个属性以保持对单元格的引用:
@property (strong, nonatomic) UITableViewCell *prototypeCell
使用一种方法将当前单元格引用保存到该属性以便使用它:
- (id)prototypeCellatIndexPath:(NSIndexPath *)indexPath {
NSString *cellID = @"MyCell";
if (!_prototypeCell) {
_prototypeCell = [self.tableView dequeueReusableCellWithIdentifier:cellID];
}
return _prototypeCell;
}
从原型(prototype)及其 contentSize 获取 UITableViewCell 的 UITableView 我获取高度并在 heighForRowAtIndexPath 下返回它: 来自以下方法:
-(int)heightForThreadAtIndexPath:(NSIndexPath *)indexPath {
_prototypeCell = [self prototypeCellatIndexPath:indexPath];
[_prototypeCell.contentView setNeedsLayout];
[_prototypeCell.contentView layoutIfNeeded];
int footer = [_prototypeCell.tableView numberOfSections]*_prototypeCell.tableView.sectionFooterHeight;
int header = [_prototypeCell.tableView numberOfSections]*_prototypeCell.tableView.sectionHeaderHeight;
int height = ceilf(_prototypeCell.tableView.contentSize.height) + _prototypeCell.tableView.contentOffset.y + _prototypeCell.tableView.contentInset.bottom + _prototypeCell.tableView.contentInset.top + header + footer;
NSLog(@"%i, %i", (int)ceilf(_prototypeCell.tableView.contentSize.height), height);
return height;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return [self heightForThreadAtIndexPath:indexPath];
}
我从 prototypeCell 返回的 contentSize.height 是错误的,它与 UITableView 的真实 contentSize 不匹配,但是当我记录真实contentSize 在 CustomCell Class 下显示正确的 contentSize,这与 prototypeCell 下的不同。
这让我想知道也许我应该尝试使处于特定状态的单元格出队以获得正确的 contentSize,但日志显示相同的值。
我进行了大量研究并尝试了不同的想法,但到目前为止都没有奏效。不知道有没有人和我实现过类似的事情,并解决了这个问题。如果你能给我一个想法或其他东西,那就太好了。
最佳答案
正如您所说,heightForRowAtIndexPath 委托(delegate)方法在自动调用时不会为您提供行的动态高度。相反,您必须明确地将其称为:
[self delegateMethod] 即 [self tableView:tableView cellForRowAtIndexPath:indexPath];
如果您将主 tableView 声明为 IBOutlet,如 myTableView,那么即使调用 [self.myTableView cellForRowAtIndexPath:indexPath] 也不会工作!!
我已经测试了代码,这对我有用:
在 MainTableViewController.m 中:
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 7;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"tableViewCellMain"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"tableViewCellMain"];
}
UITableView *tableViewChild = [[UITableView alloc] initWithFrame:CGRectMake(cell.frame.origin.x, cell.frame.origin.y, tableView.frame.size.width, tableView.frame.size.height) style:UITableViewStylePlain];
[self.cls setNumberOfRows:indexPath.row+1];
[tableViewChild setDelegate:self.cls];
[tableViewChild setDataSource:self.cls];
[tableViewChild setSeparatorStyle:UITableViewCellSeparatorStyleNone];
[tableViewChild setScrollEnabled:NO];
[tableViewChild reloadData];
[cell addSubview:tableViewChild];
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
CGFloat height = cell.frame.size.height;
for (int i=0; i<cell.subviews.count; i++) {
UITableView *childTableView = (UITableView*) [cell.subviews lastObject];
height = childTableView.contentSize.height;
}
NSLog(@"%f",height);
return height;
}
我已将另一个类设置为 childTableView 的委托(delegate)以获取其数据。
在 ChildTableViewController.m 中:
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.numberOfRows;
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"tableViewCellChild"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"tableViewCellChild"];
}
[cell.textLabel setText:[NSString stringWithFormat:@"%ld",indexPath.row]];
UIColor *cellTextColor = [UIColor blackColor];
switch (indexPath.row)
{
case 0: cellTextColor = [UIColor redColor]; break;
case 1: cellTextColor = [UIColor greenColor]; break;
case 2: cellTextColor = [UIColor blueColor]; break;
case 3: cellTextColor = [UIColor magentaColor]; break;
case 4: cellTextColor = [UIColor purpleColor]; break;
default: break;
}
[cell.textLabel setTextColor:cellTextColor];
[tableView sizeToFit];
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 30;
}
您将得到如下图所示的工作:
我的 Storyboard是这样的:
您可以使用任何方式为 mainTableView 生成动态内容,而不必为 childTableView 使用另一个类。
关于ios - 获取 heightForRowAtIndexPath : in iOS 8 下单元格的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31854340/
有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge
我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c
我安装了ruby版本管理器,并将RVM安装的ruby实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby。有没有办法让emacs像shell一样尊重ruby的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit
我想让一个yaml对象引用另一个,如下所示:intro:"Hello,dearuser."registration:$introThanksforregistering!new_message:$introYouhaveanewmessage!上面的语法只是它如何工作的一个例子(这也是它在thiscpanmodule中的工作方式。)我正在使用标准的rubyyaml解析器。这可能吗? 最佳答案 一些yaml对象确实引用了其他对象:irb>require'yaml'#=>trueirb>str="hello"#=>"hello"ir
我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur
如何在Ruby中获取BasicObject实例的类名?例如,假设我有这个:classMyObjectSystem我怎样才能使这段代码成功?编辑:我发现Object的实例方法class被定义为returnrb_class_real(CLASS_OF(obj));。有什么方法可以从Ruby中使用它? 最佳答案 我花了一些时间研究irb并想出了这个:classBasicObjectdefclassklass=class这将为任何从BasicObject继承的对象提供一个#class您可以调用的方法。编辑评论中要求的进一步解释:假设你有对象