UIImageView вначале не отображает изображение в UITableViewCell

У меня есть UITableView который загружает изображения из службы. Он извлекает URL-адреса и загружает изображения с помощью NSURLSession.sharedSession().dataTaskWithURL :

 NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: { (data, _, error) -> Void in guard let data = data where error == nil, let image = UIImage(data: data) else { print(error?.localizedDescription) return } dispatch_async(dispatch_get_main_queue()) { [unowned self] in self.pictureView.image = image self.pictureView.layoutIfNeeded() } }).resume() 

UIImageView – это выход на сцену раскадровки. UIImageView содержимого UIImageView – это Aspect Fit.

UIImageView для видимых ячеек первоначально отображается пустым (без изображения), хотя я подтвердил, что изображение было установлено. Пока камера не будет прокручена / на экране, ячейка будет перерисовываться (?) И отображать изображение.

Так что это похоже на какую-то проблему времени, но я не могу понять. Я попытался вызвать все из следующего в блоке dispatch_async после того, как изображение установлено:

 self.pictureView.setNeedsDisplay() self.pictureView.setNeedsUpdateConstraints() self.pictureView.setNeedsLayout() self.pictureView.reloadInputViews() 

Ни одна из этих проблем не устраняет проблему. Что вызывает отображение этого изображения только после прокрутки ячейки / просмотра?

EDIT: Может быть важно отметить, что это происходит внутри ниба и связанного с ним класса. Загружается ниб, затем я запускаю загрузку. Мне интересно, не UIImageView ли UIImageView , и к моменту загрузки моего изображения и установки в UIImageView завершение макета завершено. Затем, перемещая ячейку (содержащую ниб) на экране, ячейка снова выполняет макет, и все отображается правильно. Просто догадаться, и я все еще придерживаюсь этого.

EDIT 2: Дальнейшее разъяснение процесса:

1) Мой UIViewController содержит UITableView .

2) Этот UITableView загружает ячейки из пользовательского класса UITableViewCell называемого PostCell.

3) Все содержимое PostCell – это одно представление, загруженное из ножа, называемого PostView (с классом PostView). Эта нагрузка происходит во время init:style:reuseIdentifier в PostCell:

 postView = NSBundle.mainBundle().loadNibNamed("PostView", owner: self, options: nil).first as? PostView 

4) Затем я устанавливаю объект Post на postView :

 postView.post = Post 

Обратите внимание, что это происходит после того, как awakeFromNib() вызывается в PostView.

5) Свойство post на PostView имеет наблюдателя didSet который didSet загрузку изображения на основе URL-адреса в post объекте (код выше). Изображение загружается и устанавливается в UIImageView именем pictureView .

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

Вот код для tableView(_:cellForRowAtIndexPath:) :

 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { var cell = tableView.dequeueReusableCellWithIdentifier(postCellIdentifier) as? PostCell if cell == nil { cell = PostCell() } if let postCell = cell, let postArray = postArray, let post = postArray[indexPath.row] { postCell.post = post return postCell } // This section is hit during a refresh. let emptyCell = UITableViewCell() emptyCell.contentView.backgroundColor = .whiteColor() return emptyCell } 

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

Я обнаружил, что если я « UIImageView » UIImageView , предварительно установив изображение-заполнитель в nib, загрузите его в этот UIImageView , изображение будет отображаться на высоте заполнителя. Когда я снова вытащил эту ячейку из UIImageView снова UIImageView , UIImageView покрасит изображение с правильным размером, используя установку ограничений в наконечнике.

Таким образом, кажется, что ограничения и размер UIImageView были установлены к тому времени, когда загружается изображение, и вытягивание его / на экране вызывает перерисовку, которая изменяет размер изображения должным образом. Если бы я мог программно запускать эту перерисовку, это помогло бы, но см. Выше для того, что я уже пробовал.

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

Здесь он находится в действии. Обратите внимание, что я установил изображение-заполнитель в наконечнике. Это, по-видимому, приводит к тому, что изображение будет отображаться при первоначальной загрузке, но по размерам заполнителя. При прокрутке его на экране кратковременное изменение размера, когда оно отображается правильно. введите описание изображения здесь

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

Я использую PostView nib в другом месте в своем приложении без проблем. Когда он загружается, размер изображения будет правильно установлен. Кажется, проблема только в том, что nib встроен в UITableViewCell .

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

Я нашел причину этой проблемы, вызванную в viewDidLoad моего UIViewController :

 tableView.estimatedRowHeight = 500 tableView.rowHeight = UITableViewAutomaticDimension 

Использование автоматического измерения приводит к начальной неправильной высоте строки. По какой-то причине прокрутка ячейки / в представлении будет правильно подсчитать высоту строки, и изображение будет отображаться на правильной высоте. Удаление этого кода приведет к отображению изображения, но высота строки не может быть использована для расчета автоматической высоты. Каков наилучший метод автоматического расчета высоты строк и все еще избежать этой проблемы?

5 Solutions collect form web for “UIImageView вначале не отображает изображение в UITableViewCell”

вы можете попробовать это расширение:

 extension UIImageView { func downloadedFrom(link link:String, contentMode mode: UIViewContentMode) { guard let url = NSURL(string: link) else {return} contentMode = mode NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: { (data, response, error) -> Void in guard let httpURLResponse = response as? NSHTTPURLResponse where httpURLResponse.statusCode == 200, let mimeType = response?.MIMEType where mimeType.hasPrefix("image"), let data = data where error == nil, let image = UIImage(data: data) else { return } dispatch_async(dispatch_get_main_queue()) { () -> Void in self.image = image } }).resume() } } 

И тогда вы можете поместить эту строку туда, где хотите.

 cell.cellPhoto.downloadedFrom(link: "customImageUrl", contentMode: .ScaleAspectFit) //Try changing contentMode 

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

 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { ... if let postCell = cell, let postArray = postArray, let post = postArray[indexPath.row] { // set the post with image after the cell is sized correctly dispatch_async(dispatch_get_main_queue()) { postCell.post = post } return postCell } 

Убедитесь, что вы правильно настроили ограничения в файле nib ячейки.

Я также предлагаю использовать метод registerNib внутри метода viewDidLoad контроллера:

 tableView?.registerNib(UINib(nibName: "PostCellName", bundle: NSBundle.mainBundle()), forCellReuseIdentifier: postCellIdentifier) 

Вы видели сессию 226 WWDC 2014 ? Возможно, видео может пролить свет на вашу проблему.

На сессии WWDC они используют self.tableView.estimatedRowHeight = 100.0; которые вы сделали ✅, а затем они говорят, что вам не нужна какая-либо фиктивная прототипная ячейка из контроллера табличного представления.

Проблема тогда в том, что когда раскадровка загружает представление таблицы, он устанавливает свойство rowHeight в значение из построителя xib / interface. Чтобы использовать ячейки с автоматическим калибровкой, вам нужно установить estimatedRowHeight rowHeight и оставить rowHeight тем, что должно быть по умолчанию – UITableViewAutomaticDimension . ( который вы сделали ) ✅

self.tableView.rowHeight = UITableViewAutomaticDimension

⚠️ Новая проблема заключается в том, что первые ячейки загружаются до того, как у вас будет истинная высота строки. Трюк, возможно, заставит перезагрузить таблицу, когда появится представление?

 [super viewDidAppear:animated] [self.tableView reloadData] 

Если это не сработает, возможно, вы случайно настроили явный contentWidth / Height на то, что заставляет его не иметь правильного размера? "

После завершения загрузки вам необходимо перезагрузить данные таблицы. попробуйте вызвать self.tableview.reloadData() внутри блока dispatch_async

А также, если вы хотите загрузить изображение из URL асинхронно, я рекомендую использовать Kingfisher

После изучения курса редактирования (8 в настоящее время) и обновлений от ваших респондентов кажется, что вы используете ту же ошибку в методе init, которая вызвала ошибки в init, упомянутые здесь .

Кредит должен быть предоставлен Prcela на правильном пути с регистрацией наконечника, но более элегантное решение представлено ниже:

Самый простой способ (доступный с iOS 5.0) создать пользовательскую ячейку таблицы в файле nib – использовать registerNib: forCellReuseIdentifier: в контроллере табличного представления. Большим преимуществом является то, что dequeueReusableCellWithIdentifier: затем автоматически создает экземпляр ячейки из файла nib, если это необходимо. Вам больше не понадобится if (cell == nil) … part.

В контроллере Table View под viewDidLoad

 [self.tableView registerNib:[UINib nibWithNibName:@"CueTableCell" bundle:nil] forCellReuseIdentifier:@"CueTableCell"]; 

В cellForRowAtIndexPath добавьте

 CueTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CueTableCell"]; // setup cell return cell; 

Ячейки, загруженные из файла nib, создаются с использованием initWithCoder, вы можете переопределить это в своем подклассе, если это необходимо. Для модификации элементов интерфейса вы должны переопределить awakeFromNib (не забудьте вызвать «супер»).

Хотел бы я взять кредит за такое изящное решение, но этот кредит принадлежит Мартину Р с той же должности.

  • Обновление высоты таблицы калибровки со шкалой просмотра с текстовым представлением
  • Прокрутка TTTableViewControllerToTop не работает
  • как перезагрузить tableview другого uiviewcontroller в текущем диспетчере представлений
  • commitEditingStyle не запускается
  • Учебное пособие по перетаскиванию элемента из UITableView в UITableView
  • Сделать UITableViewHeaderFooterView неличным
  • Splitviewcontroller с двумя табличными представлениями, делегировать проблему
  • пространство между заголовком и ячейкой таблицы
  • Autolayout + UITableView генерирует заголовки фантомных разделов на iOS 6
  • Подэкран UITableViewCell исчезает при выборе (но содержимое в этом подвью видимо)
  • Как получить представление таблицы для прокрутки над изображением?
  • Interesting Posts
    PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.