【发布时间】:2021-08-31 11:00:09
【问题描述】:
我有一个UIViewController,它提供一个UIDocumentPicker 来选择PDF 文件,并包含一个显示它们的UICollectionView(每个单元格都包含一个PDFView 来这样做)。
代码如下:
import MobileCoreServices; import PDFKit; import UIKit
class ViewController: UIViewController {
var urls: [URL] = []
@IBOutlet weak var collectionView: UICollectionView!
@IBAction func pickFile() {
DispatchQueue.main.async {
let documentPicker = UIDocumentPickerViewController(documentTypes: [kUTTypePDF as String], in: .import)
documentPicker.delegate = self
documentPicker.modalPresentationStyle = .formSheet
self.present(documentPicker, animated: true, completion: nil)
}
}
override func viewDidLoad() {
collectionView.register(UINib(nibName: PDFCollectionViewCell.identifier, bundle: .main),
forCellWithReuseIdentifier: PDFCollectionViewCell.identifier)
}
init() { super.init(nibName: "ViewController", bundle: .main) }
required init?(coder: NSCoder) { fatalError() }
}
extension ViewController: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PDFCollectionViewCell.identifier, for: indexPath) as! PDFCollectionViewCell
cell.pdfView.document = PDFDocument(url: urls[indexPath.row])
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return urls.count
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
CGSize(width: 150, height: 150)
}
}
extension ViewController: UIDocumentPickerDelegate {
// MARK: PDF Picker Delegate
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
controller.dismiss(animated: true, completion: nil)
}
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
controller.dismiss(animated: true, completion: {
DispatchQueue.main.async {
self.urls.append(contentsOf: urls)
self.collectionView.reloadData()
}
})
}
}
class PDFCollectionViewCell: UICollectionViewCell {
static let identifier = "PDFCollectionViewCell"
@IBOutlet weak var pdfView: PDFView! { didSet { setPdfViewUI() } }
func setPdfViewUI() {
pdfView.displayMode = .singlePage
pdfView.autoScales = true
pdfView.displayDirection = .vertical
pdfView.isUserInteractionEnabled = false
}
}
现在,出于某种原因,collectionView.reloadData() 实际上只能在两次中使用一次。它第一次工作,然后第二次没有任何反应,然后第三次再次使用三个预期元素更新集合视图...
我意识到,即使我正在调用 reloadData(),当这种情况发生时,dataSource 和委托方法 (numberOfItems/cellForItem) 也不会被调用。
知道发生了什么吗?
感谢您的帮助!
编辑:我可以确保我在 viewDidLoad/appear 方法中没有任何其他代码,pickFile 函数实际上被正常调用,并且 URL 被正确获取,urls在调用 reloadData() 之前,数组正在更新。
另外,我已经对UITableView 和UICollectionView 进行了尝试,在每种情况下我都遇到了这个问题。感觉就像我使用PDFView 或文档选择器有问题。
【问题讨论】:
-
viewWillAppear()/viewDidAppear()中是否还有其他问题在此处不可见? -
嗨@TarunTyagi,绝对不是,我已经粘贴了整个代码(顺便说一句,除了 XIB 文件)
-
您是否确保异步块内部的
reloadData在您期望的时候被调用?也许还要确保您附加的urls数组非空。另外,我没有看到调用pickFile的内容,我想知道pickFile的documentPicker是否存在释放问题,因为它是在该调度块内创建的? -
@WongWray 感谢您的评论。我确保了你所说的一切,我什至创建了一个
TestCollectionView子类,它覆盖了UICollectionView及其函数reloadData()以记录我实际输入此方法的事实,这就是发生的事情。而且我还检查了urls不为空,pickFile执行良好。
标签: ios swift uicollectionview pdfkit