0

У меня есть UITableView со многими строками (+1000). Я получаю строки из этих UITableView один раз с помощью NSFetchedResultsController и fetchBatchSize в viewDidLoad, как показано ниже:Lazy loading heightForRowAtIndexPath в UITableView со многими строками

@interface MessagesViewController() 
@property (nonatomic, strong) NSFetchedResultsController *messagesFRC; 
@end 



@implementation MessagesViewController 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    if (self.messagesFRC == nil) { 

     // Read in Model.xcdatamodeld 
     NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil]; 
     NSPersistentStoreCoordinator *psc = 
     [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model]; 

     // Where does the SQLite file go? 
     NSArray *documentDirectories = 
     NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, 
              NSUserDomainMask, 
              YES); 
     // Get one and only document directory from that list 
     NSString *documentDirectory = [documentDirectories firstObject]; 
     NSString *path = [documentDirectory stringByAppendingPathComponent:@"model.sqlite"]; 

     NSURL *storeURL = [NSURL fileURLWithPath:path]; 
     NSError *error = nil; 
     if (![psc addPersistentStoreWithType:NSSQLiteStoreType 
           configuration:nil 
             URL:storeURL 
            options:nil 
             error:&error]) { 
      @throw [NSException exceptionWithName:@"OpenFailure" 
              reason:[error localizedDescription] 
             userInfo:nil]; 
     } 

     // Create the managed object context 
     NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init]; 
     context.persistentStoreCoordinator = psc; 

     NSFetchRequest *request = [[NSFetchRequest alloc] init]; 

     NSString *entityName = @"Message"; 
     NSString *sortAttribute = @"timestamp"; 


     NSEntityDescription *e = [NSEntityDescription entityForName:entityName 
              inManagedObjectContext:context]; 

     request.entity = e; 


     NSSortDescriptor *sd = [NSSortDescriptor 
           sortDescriptorWithKey:sortAttribute 
           ascending:NO]; 
     request.sortDescriptors = @[sd]; 

//  request.fetchLimit = 30; 
     request.fetchBatchSize = 60; 


     self.messagesFRC = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:context sectionNameKeyPath:nil cacheName:nil]; 


     NSError *error3 = nil; 
     if (![self.messagesFRC performFetch:&error3]) { 
      NSLog(@"Failed to initialize FetchedResultsController: %@\n%@", [error localizedDescription], [error userInfo]); 
      abort(); 
     } 

     self.messagesFRC.delegate = self; 
    } 
} 

@end 

Также я установить высоту каждой ячейки с heightForRowAtIndexPath в этом контроллере:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
{   
    if ([tableView isEqual:self.tableView]) { 
     NSManagedObject *row = [self.messagesFRC objectAtIndexPath:indexPath]; 
     NSString *messageText = [[NSString alloc] initWithData:[row valueForKey:@"text"] encoding:NSUTF8StringEncoding]; 
     messageText = [[GeneralHelper convertHtmlToString:messageText] stringByReplacingOccurrencesOfString:@"\n" withString:@" "]; 
     //  messageText = @"yes\r\nnew"; 

     NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new]; 
     paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping; 
     paragraphStyle.alignment = NSTextAlignmentRight; 
     //  paragraphStyle. 


     NSDictionary *attributes = @{NSFontAttributeName: self.messageFont, 
            NSParagraphStyleAttributeName: paragraphStyle}; // TODO: Font 


     CGFloat width = CGRectGetWidth(tableView.frame)-kMessageTableViewCellAvatarHeight; 
     width -= 25.0; 

     CGRect titleBounds = [[row valueForKey:@"title"] boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:NULL]; 
     CGRect bodyBounds = [messageText boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:NULL]; 

     if (messageText.length == 0) { 
      return 0.0; 
     } 

     CGFloat height = CGRectGetHeight(titleBounds); 
     height += CGRectGetHeight(bodyBounds); 
     height += 40.0; 

     if (height < kMessageTableViewCellMinimumHeight) { 
      height = kMessageTableViewCellMinimumHeight; 
     } 

     return height; 
    } 
    else { 
     return kMessageTableViewCellMinimumHeight; 
    } 
} 

Проблема в том, что загружая UITableView длительное время (более 15 секунд) из-за установки высоты всех ячеек в начале рабочего процесса. Поэтому мне нужна ленивая загрузка по heightForRowAtIndexPath для каждых 30 ячеек, а затем, прокручивая вверх и вниз, получите следующую 30 ячеек.

Кроме того, я проверить UITableViewAutomaticDimension для IOS 7+, но он имел очень высокую загрузку процессора:

-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(nonnull NSIndexPath *)indexPath { 
    return UITableViewAutomaticDimension; 
} 

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
    return UITableViewAutomaticDimension; 
} 

Как решить эту проблему?

+0

Вы можете попробовать использовать '- tableView: expectedHeightForRowAtIndexPath:' – Avi

+0

Прочтите его еще раз, в последней части вопроса я упомянул об этом. –

+0

Кроме того, представление таблицы загружает только видимые ячейки, поэтому для них будет называться 'heightForRowAtIndexPath'. Если вы регистрируете или устанавливаете точку останова, вы можете это увидеть сами. – Avi

ответ

0

Вы можете использовать счетчик say numberOfRenderedRows. numberOfRenderedRows устанавливается в 30 в начале, и это будет добавлено 30 каждый раз, когда пользователь будет прокручивать таблицу и обновляться. Это будет счет строк таблицы. Используйте следующую команду, чтобы добавить обновление.

#

UIRefreshControl* refreshControl = [[UIRefreshControl alloc]init]; 
[refreshControl addTarget:self action:@selector(actionRefreshRows) forControlEvents:UIControlEventValueChanged]; 
[tableView addSubview:refreshControl]; 
+0

Не могли бы вы объяснить это больше? Некоторые примеры или документация? Где его использовать? Спасибо –

+0

Проверьте следующие ссылки для объяснения UIRefreshControl ## http://code.tutsplus.com/tutorials/working-with-uirefreshcontrol--mobile-14712 ## https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIRefreshControl_class/ –

0

Может быть, вы должны попытаться сделать ваши клетки себя проклейки.

Установив соответствующие ограничения для ячейки прототипа, вы можете избавиться от своего метода heightForRowAtIndexPath.

The documentation is here.

+0

Хороший способ и работает (начальное время значительно сократилось), однако при быстрой прокрутке он вызывает высокую загрузку процессора –

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