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 :: значение ноль» потому self.cell .comment.text не получает ничего к тому времени, когда я установил высоту ячейки, но это происходит только тогда, когда вызывается highForRowAtIndexPath.

Многие люди прокомментировали этот ответ, что этот метод работает очень хорошо, поэтому я думаю, что я что-то упустил?

Редактировать

Я устанавливаю 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;} 
+0

Каково значение «текста», когда вы достигаете этой строки? – Fogmeister

+0

Я получаю ноль. если я прокомментирую все это, без ошибок, я вижу все комментарии к моему табло, чтобы они все прошли. – durazno

+0

Я думаю, вы сбиваете с толку, что такое self.cell. Где вы устанавливаете 'self.cell.comment.text'? – Fogmeister

ответ

4

Ваша проблема, как вы уже комментарий является то, что функция heightForRowAtIndexPath вызывается перед клетки заселяются.

Для каждой клетки, которые становятся видимым его первым называет

  • высоты ПОЛУЧИТЬ эту клетку
  • Заселите клетки

Таким образом, вы знаете, что

а) ваш текст не заполненный по ячейке

б) какой-либо другой текст может быть внутри, bec ause apple использует повторно используемые ячейки, поэтому 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; 
} 

этот пример работает.

+0

Все еще не работает. Мне, возможно, придется найти другой способ. – durazno

+0

Итак, если я понимаю, что вы говорите, вместо установки comment.text непосредственно из [object objectForKey: @ "comment"]; который я извлекаю из Parse, сначала извлеките данные, поместите их в массив, а затем comment.text = [newArray getObjectAtIndex: indexPath.row] ;? – durazno

+0

No: D Что я пытаюсь сказать, так это то, что вы не должны полагаться на визуальный текст внутри ячейки, потому что этот текст может быть нулевым или неправильным. Вместо этого вам нужно получить текст из бизнес-логики, неважно, является ли это объектом карты, массива или синтаксического анализа ... Вы должны быть уверены, что этот текст действителен и перед вызовом программы для высоты ячейки. Что вы со мной «все еще не работали»? –

0

В heightForRowAtIndexPath:

Для ширины, я думаю, что вы можете это исправить, и не нужна эта строка:

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

Для текста комментария

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

Попробуйте

NSString *text = [object objectForKey:@"comment"]; 
0

Провел весь день, пытаясь понять это и, наконец, узнал, что решение было очень простым, мне просто нужно было знать, как лучше использовать Parse.

Благодаря Марко, я узнал, как UITableView действительно работает, и это здорово, но решение моей проблемы было несколько иным.

Как всегда, моя проблема предполагала, что heightForRowAtIndexPath будет вызван после заполнения всех ячеек, но мне не нужен массив для сохранения объектов или внесения каких-либо изменений. Parse, очевидно, сохраняет все извлеченные объекты до того, как heightForRowAtIndexPath вызывается, и все они находятся в self.objects.

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

И, как страстно предложил Энди, теперь я использую 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);} 

Это, безусловно, работает.

Смежные вопросы