#ios #swift #uicollectionview #uicollectionviewcell
Вопрос:
У меня есть UICollectionView
ячейки с ячейками двух типов; некоторые загружают изображения с URL-адреса, а другие загружают метаданные с URL-адреса и отображают их с LPLinkView
помощью .
Ниже приведен мой код для ячейки, которая отображает данные с помощью LPLinkView
:
import UIKit
import LinkPresentation
class LinkItemLinkPreviewCell: UICollectionViewCell {
static let identifier = "kLinkPreviewCollectionViewCell"
var linkView: LPLinkView?
var urlMetadata: LPLinkMetadata?
@IBOutlet var containerView: UIView? = UIView()
@IBOutlet var titleLabel: UILabel? = UILabel()
@IBOutlet var dateLabel: UILabel? = UILabel()
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.clipsToBounds = true
self.autoresizesSubviews = true
self.layer.cornerRadius = 20
}
override func prepareForReuse() {
super.prepareForReuse()
}
var linkItem: LinkPostDataObject? {
didSet {
titleLabel?.text = linkItem?.postTitle ?? ""
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd hh:mm"
dateLabel?.text = df.string(from: toDate((linkItem?.timeSent)!/1000)!)
let provider = LPMetadataProvider()
let url = URL(string: linkItem!.url)
if url != nil {
provider.startFetchingMetadata(for: URL(string: linkItem!.url)!) { (metadata, error) in
if let md = metadata {
DispatchQueue.main.async { [self] in
linkView = LPLinkView()
linkView?.metadata = md
linkView!.frame = containerView!.frame
containerView?.addSubview(linkView!)
linkView!.isUserInteractionEnabled = false
urlMetadata = metadata
}
}
}
}
}
}
}
Ниже приведен код для UICollectionViewCell
отображения изображения с URL-адреса:
import UIKit
class LinkItemImageCell: UICollectionViewCell {
static let identifier = "kImageCollectionViewCell"
@IBOutlet var imageView: UIImageView? = UIImageView()
@IBOutlet var titleLabel: UILabel? = UILabel()
@IBOutlet var dateLabel: UILabel? = UILabel()
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.clipsToBounds = true
self.autoresizesSubviews = true
self.layer.cornerRadius = 20
}
override func prepareForReuse() {
super.prepareForReuse()
}
var linkItem: LinkPostDataObject? {
didSet {
titleLabel?.text = linkItem?.postTitle ?? ""
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd hh:mm"
dateLabel?.text = df.string(from: toDate((linkItem?.timeSent)!/1000)!)
if linkItem?.url.isImage() == true {
let url = URL(string: linkItem!.url)
url!.getImageData(from: url!) { (data, response, error) in
guard let data = data, error == nil else { return }
DispatchQueue.main.async() { [self] in
imageView?.image = UIImage(data: data)
}
}
}
}
}
}
А ниже приведен код для моего ViewController:
import UIKit
class LinkCollectionViewController : UIViewController, UICollectionViewDelegate,UICollectionViewDataSource {
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var collectionNameLabel: UILabel!
@IBOutlet weak var collectionSubTitleLabel: UILabel!
@IBOutlet weak var collectionCreatorLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let backButton = UIBarButtonItem()
backButton.title = "Inbox"
self.navigationController?.navigationBar.topItem?.backBarButtonItem = backButton
collectionNameLabel.text = airlockStore.selectedChannel.channelName
collectionSubTitleLabel.text = airlockStore.selectedChannel.channelDescription
collectionCreatorLabel.text = airlockStore.selectedChannel.creator
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
collectionView.alwaysBounceVertical = true
collectionView.register(UINib(nibName: "LinkImageItemCell", bundle: nil), forCellWithReuseIdentifier: "kImageCollectionViewCell")
collectionView.register(UINib(nibName: "LinkItemLinkPreviewCell", bundle: nil), forCellWithReuseIdentifier: "kLinkPreviewCollectionViewCell")
collectionView.reloadItems(at: collectionView.indexPathsForVisibleItems)
collectionView.reloadData()
NotificationCenter.default.addObserver(self, selector: #selector(self.updateLinkCollection), name: Notification.Name("Link_Collection_Updated"), object: nil)
}
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.setNavigationBarHidden(false, animated: animated)
}
@objc func updateLinkCollection() {
collectionView.reloadData()
collectionView.reloadItems(at: collectionView.indexPathsForVisibleItems)
}
// MARK: - UICollectionViewDataSource Delegate
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return airlockStore.selectedChannel.linkPosts.count
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
// MARK: - UICollectionViewDelegate
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
//Image
if airlockStore.selectedChannel.linkPosts.reversed()[indexPath.item].url.isImage() == true {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: LinkItemImageCell.identifier, for: indexPath) as? LinkItemImageCell
else { preconditionFailure("Failed to load collection view cell") }
cell.linkItem = airlockStore.selectedChannel.linkPosts.reversed()[indexPath.item]
return cell
}
//URL
else {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: LinkItemLinkPreviewCell.identifier, for: indexPath) as? LinkItemLinkPreviewCell
else { preconditionFailure("Failed to load collection view cell") }
cell.linkItem = airlockStore.selectedChannel.linkPosts.reversed()[indexPath.item]
return cell
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "GoToLinkBlockViewController", sender: self)
airlockStore.selectedLinkBlock = airlockStore.selectedChannel.linkPosts.reversed()[indexPath.item]
guard let cell: LinkItemLinkPreviewCell = collectionView.cellForItem(at: indexPath)! as? LinkItemLinkPreviewCell else {
return
}
airlockStore.selectedLinkBlock.urlMetadata = cell.urlMetadata
}
}
Что я замечаю, так это то, что ячейки с LPLinkView
буквами » s » очень медленно отображают данные, а также то, что при прокрутке происходит много обновлений UICollectionView
.
Любые идеи или рекомендации о том, как я мог бы повысить производительность, здесь приветствуются; на самом деле я просто пытаюсь не перезагружать изображения/URL-адреса ячеек при прокрутке.
Ответ №1:
У меня нет времени разбираться в вашем коде, поэтому мой ответ будет общим:
Когда в представлении таблицы/коллекции отображаются данные, которые необходимо извлечь по сети, загрузите эти данные в модель данных, а не в ячейки. Когда загрузка сети завершится и эта запись в модели будет обновлена, попросите соответствующую ячейку перезагрузиться.
Если вы загружаете данные в свои ячейки при прокрутке, данные, которые вы загрузили ранее, будут потеряны, а если вы прокрутите назад, вам придется загрузить их снова. В идеале сохраните загруженные данные в файлы в каталоге кэша, чтобы они по-прежнему были доступны, если пользователь закроет контроллер представления, а затем снова откроет его.
Если вы установите загруженные данные в свою модель, то при прокрутке и прокрутке назад ячейка будет отображаться правильно, как только она появится.