0

我已经尝试了很多关于 SO 的答案,但没有真正奏效。我可能做错了什么,所以我需要有人指出我做错了什么..

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

    NSLog(@"text : %@", self.cell.comment.text);

    NSString *text = self.cell.comment.text;
    CGFloat width = self.cell.frame.size.width;
    UIFont *font = [UIFont fontWithName:@"HelveticaNeue" size:15];
    NSAttributedString *attributedText =
    [[NSAttributedString alloc] initWithString:text
                                    attributes:@{NSFontAttributeName: font}];
    CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX}
                                               options:NSStringDrawingUsesLineFragmentOrigin
                                               context:nil];
    CGSize size = rect.size;
    CGFloat height = ceilf(size.height);

    return height;
}

我得到“NSInvalidArgumentException”,原因是“NSConcreteAttributedString initWithString:: nil value”,因为 self.cell.comment.text 在我设置单元格高度时没有得到任何东西,但它确实在调用 heightForRowAtIndexPath 时没有。

许多人对该答案发表了评论,认为这种方法效果很好,所以我想我错过了什么?

编辑

我在这里设置 self.cell.comment.text -

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object{
static NSString *simpleTableIdentifier = @"cell";

self.cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (self.cell == nil) {
    self.cell = [[CommentCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}

// Configure the cell

self.cell.comment.text = [object objectForKey:@"comment"];
[self.cell.comment sizeToFit];

return self.cell;}
4

3 回答 3

4

您已经评论的问题是heightForRowAtIndexPath在填充单元格之前调用了该函数。

对于每个可见的单元格,它首先调用

  • 获取此单元格的高度
  • 填充单元格

所以你知道

a)您的文本尚未填充到单元格上

b) 一些其他文本可能在里面,因为苹果使用可重复使用的单元格,所以 UITableView 可以抓取一些单元格(具有不同的文本)并尝试调整它的大小然后填充它。

在您的情况下,它将抓取一些其他文本,将单元格调整为其大小,然后用其他一些(可能)与以前的文本大小不同的文本填充它。

但是在细胞群中,您可以从一些业务逻辑(可能是数组?)中设置文本,并且您可以在此方法中获得相同的文本。

如果你打电话给细胞群

cell.comment.text = [self.someArray getObjectAtIndex:index.row];

你在你的heightForRowAtIndexPath方法中调用它。

NSString *text = [self.someArray getObjectAtIndex:index.row];

我看到你的编辑只是打电话:

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

NSLog(@"text : %@", self.cell.comment.text);

NSString *text = [object objectForKey:@"comment"];;
CGFloat width = self.cell.frame.size.width;
UIFont *font = [UIFont fontWithName:@"HelveticaNeue" size:15];
NSAttributedString *attributedText =
[[NSAttributedString alloc] initWithString:text
                                attributes:@{NSFontAttributeName: font}];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX}
                                           options:NSStringDrawingUsesLineFragmentOrigin
                                           context:nil];
CGSize size = rect.size;
CGFloat height = ceilf(size.height);

return height;
}

添加 :

电话说你想要这样的细胞:

-------------------------
|  bla bla bla         |
------------------------
| second longer text   |
| over more line       |
------------------------

您需要在bla bla某处保存文本和“多行第二长文本”。

假设您有大小为 2 的数组。

NSArray * myTextArray = @[@"bla bla", @"second longer text over more line"];

和填充单元格时

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object{
   static NSString *simpleTableIdentifier = @"cell";

   self.cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
   if (self.cell == nil) {
        self.cell = [[CommentCell alloc] initWithStyle:UITableViewCellStyleDefault         reuseIdentifier:simpleTableIdentifier];
    }

    // Configure the cell

    self.cell.comment.text = [myTextArray objectAtIndex:indexPath.row];
    [self.cell.comment sizeToFit];

    return self.cell;
 }

因为在我们需要从业务(数组)端检查文本而不是视觉heightForRowAtIndexPath之前调用。cellForRowAtIndexPath

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

   NSLog(@"text : %@", self.cell.comment.text); // -> this is null because cell is not populated yet.

   NSString *text = [myTextArray objectAtIndex:indexPath.row]; -> this is same text as we will take when populating cell and is not random.
   CGFloat width = self.cell.frame.size.width;
   UIFont *font = [UIFont fontWithName:@"HelveticaNeue" size:15];
   NSAttributedString *attributedText =
   [[NSAttributedString alloc] initWithString:text
                                attributes:@{NSFontAttributeName: font}];
   CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX}
                                           options:NSStringDrawingUsesLineFragmentOrigin
                                           context:nil];
   CGSize size = rect.size;
   CGFloat height = ceilf(size.height);

   return height;
}

例子 :

#import "ViewController.h"

@interface ViewController ()

@property NSArray * myArray;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.myArray = @[@"Some short text",@"Some longer text that take some more space throw more lines",@"bfusdbfjdsfjs fj yfsdy fgsydu fyudsfy fyudsyu fdsy fuysdyuf ydsug fyu sdgyfgsuyff ius fhs fiusdhi ufdshu uifsd ufsdh hfiuds uifdsh fsduih ufdshu hfsd ifshui"];

}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 3;
}


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

    NSString *text = self.myArray[indexPath.row];
    CGFloat width = 300;
    UIFont *font = [UIFont fontWithName:@"HelveticaNeue" size:15];
    NSAttributedString *attributedText =
    [[NSAttributedString alloc] initWithString:text
                                attributes:@{NSFontAttributeName: font}];
    CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX}
                                           options:NSStringDrawingUsesLineFragmentOrigin
                                           context:nil];
    CGSize size = rect.size;
    CGFloat height = ceilf(size.height);

    return height;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *simpleTableIdentifier = @"cell";

    UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
    }

    // Configure the cell

    cell.textLabel.text = self.myArray[indexPath.row];
    cell.textLabel.numberOfLines = 0;
    return cell;
}

这个例子有效。

于 2015-08-13T09:10:09.617 回答
0

在 heightForRowAtIndexPath 中:

对于宽度,我认为您可以修复它,并且不需要此行:

 CGFloat width = self.cell.frame.size.width;

对于评论文本

NSString *text = self.cell.comment.text;

尝试这个

NSString *text = [object objectForKey:@"comment"];
于 2015-08-13T11:05:45.890 回答
0

花了一整天的时间试图解决这个问题,最后发现解决方案非常简单,我只需要知道如何更好地使用 Parse。

感谢 Marko,我了解了 UITableView 的真正工作原理,这很棒,但我的问题的解决方案有点不同。

正如每个人都建议的那样,我的问题是假设在填充所有单元格后会调用 heightForRowAtIndexPath,但我不需要数组来保存对象或进行任何更改。Parse 显然会在调用 heightForRowAtIndexPath 之前保存所有检索到的对象,并且它们都在self.objects中。

self.cell.comment.text = [self.objects objectAtIndex:indexPath.row];

正如 Andy 热情建议的那样,我现在正在使用 Auto-size UITableViewCell。

在你的 PFQueryTableViewController

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

PFObject *object = [self.objects objectAtIndex:indexPath.row];

if (object) {
    NSString *commentString = [self.objects[indexPath.row] objectForKey:@"comment"];

    NSLog(@"commentString : %@",commentString);

    CommentCell *cell = [[CommentCell alloc] init];
    cell.textLabel.text = commentString;


    [cell setNeedsLayout];
    [cell layoutIfNeeded];

    self.height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

    self.height += 1;

}

return self.height;}

在您的 CustomCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {

    self.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
    self.textLabel.numberOfLines = 0;
    self.textLabel.translatesAutoresizingMaskIntoConstraints = NO;


    [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-6-[bodyLabel]-6-|" options:0 metrics:nil views:@{ @"bodyLabel": self.textLabel }]];
    [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-6-[bodyLabel]-6-|" options:0 metrics:nil views:@{ @"bodyLabel": self.textLabel }]];

}

return self;}


 - (void)layoutSubviews{
[super layoutSubviews];

[self.contentView setNeedsLayout];
[self.contentView layoutIfNeeded];

self.textLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.textLabel.frame);}

这绝对有效。

于 2015-08-13T15:52:07.487 回答