У меня есть 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 - это Aspect Fit.
UIImageView для видимых ячеек первоначально отображает пустое (без изображения), хотя я подтвердил, что изображение было установлено. Пока ячейка не будет прокручена/на экране, ячейка будет перерисовываться (?) И отображать изображение.
Итак, это похоже на какой-то вопрос времени, но я не могу понять это. Я попытался вызвать все следующие в блоке dispatch_async после установки изображения:
self.pictureView.setNeedsDisplay()
self.pictureView.setNeedsUpdateConstraints()
self.pictureView.setNeedsLayout()
self.pictureView.reloadInputViews()
Ничего из этого не исправить. Что вызывает отображение этого изображения только после прокрутки ячейки/просмотра?
EDIT:
Может быть важно отметить, что это происходит внутри ниба и связанного с ним класса. Загружается ниб, затем я запускаю загрузку. Я задаюсь вопросом, вырывается ли нить, и к моменту загрузки моего изображения и установки на UIImageView завершение макета завершено. Затем, перемещая ячейку (содержащую ниб) на экране, ячейка снова выполняет макет, и все отображается правильно. Просто догадаться, и я все еще придерживаюсь этого.
ИЗМЕНИТЬ 2: Дальнейшее уточнение процесса:
1) Мой UIViewController содержит a 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, который запускает загрузку изображения на основе 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, предварительно установив изображение-заполнитель в nib, загрузите его изображение в UIImageView, изображение будет отображаться на высоте заполнителя. Когда я снова вытащу эту ячейку с экрана, затем UIImageView будет рисовать изображение с правильным размером, используя установку ограничений в nib.
Таким образом, кажется, что ограничения и размер UIImageView были установлены к тому времени, когда загружается изображение, и вытаскивание его/на экране вызывает перерисовку, которая изменяет размер изображения должным образом. Если бы я мог программно запускать эту перерисовку, это помогло бы, но см. Выше для того, что я уже пробовал.
Изменить 6:
Здесь он находится в действии. Обратите внимание, что я установил образ заставки в наконечник. Это, по-видимому, приводит к тому, что изображение будет отображаться при первоначальной загрузке, но по размерам заполнителя. При прокрутке его на экране кратковременное изменение размера, когда оно отображается правильно.

Изменить 7:
Я использую PostView nib в другом месте в своем приложении без проблем. Когда он загружается, размер изображения будет правильно установлен. Кажется, проблема только в том, что nib встроен в UITableViewCell.
Изменить 8:
Я нашел основную причину этой проблемы, вызванную в viewDidLoad моего UIViewController:
tableView.estimatedRowHeight = 500
tableView.rowHeight = UITableViewAutomaticDimension
Использование автоматического измерения приводит к начальной неправильной высоте строки. По какой-то причине прокрутка ячейки/в представлении будет правильно подсчитать высоту строки, и изображение будет отображаться на правильной высоте. Удаление этого кода приведет к отображению изображения, но высота строки не может быть использована для расчета автоматической высоты. Каков наилучший способ автоматического вычисления высоты строк и все еще избежать этой проблемы?