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