我目前正在开展一个项目,我在UITableView
内嵌入UITableViewCell
。
我需要做的是禁用UITableView
的滚动并使UITableView
适合所有行的大小。但由于UITableView
继承自UIScrollView
,使用 Autolayout 并不会强制UITableView
根据其 contentSize 返回UITableViewAutomaticDimension
时强>(不是框架)。
这很容易在iOS 7之前实现,因为我使用下面的代码获得了heightForRowAtIndexPath:
下的单元格的引用:
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
int height = cell.tableView.contentSize.height;
return height;
但是在iOS 8中,它提供了 BAD_ACCESS ,因为iOS 8会在调用heightForRowAtIndexPath:
之前调用cellForRowAtIndexPath:
。
声明一个属性以保持对单元格的引用:
@property (strong, nonatomic) UITableViewCell *prototypeCell
使用方法将当前单元格引用保存到属性以便使用它:
- (id)prototypeCellatIndexPath:(NSIndexPath *)indexPath {
NSString *cellID = @"MyCell";
if (!_prototypeCell) {
_prototypeCell = [self.tableView dequeueReusableCellWithIdentifier:cellID];
}
return _prototypeCell;
}
从原型获取UITableView
的{{1}},从 contentSize 获取高度,然后从UITableViewCell
下面的方法返回:< / p>
heighForRowAtIndexPath:
我从prototypeCell返回的 contentSize.height 是错误的,它与-(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];
}
的真实contentSize不匹配,但是当我记录真实时 CustomCell Class 下的contentSize ,它显示正确的contentSize,它与prototypeCell下的不同。
这让我想知道可能我应该尝试将单元格出列到特定状态以获得正确的contentSize,但是日志显示相同的值。
我一直在研究很多并尝试不同的想法,但到目前为止都没有。我不知道是否有人试图与我做类似的事情,并解决了这个问题。如果你给我一个想法或其他什么,那将是非常好的。
答案 0 :(得分:7)
正如您所说,let session = URLSession.shared
let request = URLRequest(url: URL(string: "http://hq.sinajs.cn/list=sz000609")!)
let task = session.dataTask(with: request, completionHandler: {
(data, response, error) -> Void in
guard let data = data else { return }
var usedEncoding = String.Encoding.utf8 // Some fallback value
if let encodingName = response?.textEncodingName {
let encoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding(encodingName as CFString))
if encoding != UInt(kCFStringEncodingInvalidId) {
usedEncoding = String.Encoding(rawValue: encoding)
}
}
if let myString = String(data: data, encoding: usedEncoding) {
print("this is my string: \(myString)")
} else {
print("failed to decode data")
}
})
task.resume()
委托方法在自动调用时不会为您提供行的动态高度。相反,您必须明确地将其称为:
heightForRowAtIndexPath
即[self delegateMethod]
如果您将主tableView声明为[self tableView:tableView cellForRowAtIndexPath:indexPath];
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
:
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;
}
生成动态内容,并且不需要使用mainTableView
的其他类。
答案 1 :(得分:2)
您也可以在iOS 8中使用iOS 7方法,唯一改变的是您无法使用delegate
方法中的heightForRowAtIndexPath:
,而是调用控制器中的实际cellForRowAtIndexPath:
,所以更改行:
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
到行:
UITableViewCell* cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
应该工作。
答案 2 :(得分:1)
我设置了另一个响应,我将所有内容设置为完全动态,无法重现您的问题:
这是一个存储库:https://bitbucket.org/Kettu/dynamiccellfrorow。当我awakeForNib
计算苍蝇中的所有行并且最终值可以像在iOS 7中的scrollView contentSize
下找到时,我所做的就是调用重新加载数据。
请注意,因为在此演示项目中行数和高度完全是随机的,所以每次单元格可重复使用时,这将重新加载和闪烁。不应该在真实数据上发生。