preface
After iOS 11, Apple opened the PDFKit SDK on the iOS platform, which is mainly used to display and operate PDF files. This time, by learning PDFKit, it realized the functions of displaying PDF contents, thumbnails, directories, favorites and searches.
The official documentation
Code iBook, pure Swift written, want to learn PDFKit, you can click Star to learn.
PDFKit
Documentation in PDFKit
// Views PDFView: PDFView is used to display the PDF file. PDFThumbnailView: With PDFThumbnailView, you can get the thumbnail of the PDFCopy the code
// Model PDFDocument: represents PDF data or PDF files and defines methods for writing, searching, and selecting PDF data. PDFPage: represents a page in a PDF. You can obtain information about each page through PDFPage. PDFOutline: Represents the PDF document structure of the tree structure of the hierarchy of elements, you can get PDF outline directory information. PDFSelection: Identifies consecutive or non-consecutive selected text in the Chinese text of a PDF document. It indicates that a text is selected and can be searched in the search module.Copy the code
// Annotations PDFAnnotation: Represents the Annotations in a PDF document. PDFAction: the hop operation performed when a PDF comment is activated or an outline directory is clicked. PDFDestination: Describes the hop directory on the PDF page and is used in the hop page. PDFBorder: Optional comment border drawn entirely within the comment rectangle.Copy the code
iBook
Library page to obtain PDF related data, which can be obtained from KVC.
- PDF title
if let title = documentAttributes["Title"] as? String {
cell.title = title
}
Copy the code
- PDF author
if let author = documentAttributes["Author"] as? String {
cell.author = author
}
Copy the code
- Get the first page as the cover, which has been cached
let thumbnailCache = NSCache<NSURL.UIImage> ()let downloadQueue = DispatchQueue(label: "com.jovins.pdfview.thumbnail")
if let page = document.page(at: 0), let key = document.documentURL as NSURL? {
cell.url = key
if let thumbnail = thumbnailCache.object(forKey: key) {
cell.image = thumbnail
} else {
downloadQueue.async {
let imgWidth: CGFloat = (UIScreen.main.bounds.width - 48)/2 - 24
let imgHeight: CGFloat = 190
let thumbnail = page.thumbnail(of: CGSize(width: imgWidth, height: imgHeight), for: .cropBox)
self.thumbnailCache.setObject(thumbnail, forKey: key)
if cell.url = = key {
DispatchQueue.main.async {
cell.image = thumbnail
}
}
}
}
}
Copy the code
Initialize a DocumentModel to store PDFDocument data.
struct DocumentModel {
var title: String = ""
var author: String = ""
var coverImage: UIImage?
var url: URL?
}
Copy the code
class BookManager {
static let shared = BookManager(a)func getDocument(_ pdfDoc: PDFDocument?). -> DocumentModel {
var model = DocumentModel(a)if let document = pdfDoc, let documentAttributes = document.documentAttributes {
if let title = documentAttributes["Title"] as? String {
model.title = title
} else {
model.title = "No Title"
}
if let author = documentAttributes["Author"] as? String {
model.author = author
} else {
model.author = "No Author"
}
if document.pageCount > 0.let page = document.page(at: 0) {
let imgWidth: CGFloat = (UIScreen.main.bounds.width - 48)/2 - 24
let imgHeight: CGFloat = 190
let thumbnail = page.thumbnail(of: CGSize(width: imgWidth, height: imgHeight), for: .cropBox)
model.coverImage = thumbnail
}
if let url = document.documentURL {
model.url = url
}
}
return model
}
}
Copy the code
PDF browsing
Figure 1 is the PDF viewing details page
private lazy var pdfView: PDFView = {
let view = PDFView()
view.backgroundColor = Device.bgColor
view.autoScales = true
view.displayMode = .singlePage
view.displayDirection = .horizontal
view.usePageViewController(true, withViewOptions: [UIPageViewController.OptionsKey.spineLocation: 20])
return view
}()
self.pdfView.document = self.document
Copy the code
Figure 2 shows all the pages of the PDF
/// The core code of the page
if let doc = self.document, let page = doc.page(at: indexPath.item) {
let pageNumber = indexPath.item
cell.pageNumber = pageNumber
let key = NSNumber(value: pageNumber)
if let thumbnail = self.thumbnailCache.object(forKey: key) {
cell.image = thumbnail
} else {
let cellSize = CGSize(width: (UIScreen.main.bounds.width - 16 * 4)/3, height: 140)
downloadQueue.async {
let thumbnail = page.thumbnail(of: cellSize, for: .cropBox)
self.thumbnailCache.setObject(thumbnail, forKey: key)
if cell.pageNumber = = pageNumber {
DispatchQueue.main.async {
cell.image = thumbnail
}
}
}
}
}
Copy the code
Figure 3 shows the PDF table of contents
/// This page is the core code
let outline = self.lines[indexPath.item]
cell.titleString = outline.label
cell.pageString = outline.destination?.page?.label
var indentationLevel = -1
var parent = outline.parent
while let _ = parent {
indentationLevel + = 1
parent = parent?.parent
}
cell.indentationLevel = indentationLevel
Copy the code
Figure 4 shows the page favorites while browsing.
/// get the favorites page
if let documentURL = self.document?.documentURL?.absoluteString, let bookmarks = UserDefaults.standard.array(forKey: documentURL) as? [Int] {
self.bookmarks = bookmarks
self.collection.reloadData()
}
// Display favorites
let pageNumber = self.bookmarks[indexPath.item]
if let page = self.document?.page(at: pageNumber) {
cell.pageNumber = pageNumber
let key = NSNumber(value: pageNumber)
if let thumbnail = self.thumbnailCache.object(forKey: key) {
cell.image = thumbnail
} else {
let cellSize = CGSize(width: (UIScreen.main.bounds.width - 16 * 4)/3, height: 140)
downloadQueue.async {
let thumbnail = page.thumbnail(of: cellSize, for: .cropBox)
self.thumbnailCache.setObject(thumbnail, forKey: key)
if cell.pageNumber = = pageNumber {
DispatchQueue.main.async {
cell.image = thumbnail
}
}
}
}
}
Copy the code
Print, direct call system method.
let printInteractionController = UIPrintInteractionController.shared
printInteractionController.printingItem = self.document?.dataRepresentation()
printInteractionController.present(animated: true, completionHandler: nil)
Copy the code
Reading history
Store history in the PDF viewer page
private func storgeHistoryList(a) {
if let documentURL = self.document?.documentURL?.absoluteString {
let cache = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0].absoluteString
let key = cache.appending("com.jovins.ibook.storgeHistory")
if var documentURLs = UserDefaults.standard.array(forKey: key) as? [String] {
if !documentURLs.contains(documentURL) {
// If it does not exist, store it
documentURLs.append(documentURL)
UserDefaults.standard.set(documentURLs, forKey: key)
}
} else {
// First storage
UserDefaults.standard.set([documentURL], forKey: key)
}
}
}
Copy the code
Gets browsing records
fileprivate func refreshData(a) {
let cache = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0].absoluteString
let key = cache.appending("com.jovins.ibook.storgeHistory")
if let documentURLs = UserDefaults.standard.array(forKey: key) as? [String] {
var urls: [URL] = []
for str in documentURLs {
if let url = URL(string: str) {
urls.append(url)
}
}
self.documents = urls.compactMap { PDFDocument(url: $0)}self.tableView.reloadData()
}
}
Copy the code
search
Set up the proxy with PDFDocument and then call beginFindString to implement the search capability.
func searchBar(_ searchBar: UISearchBar.textDidChange searchText: String) {
let searchText = searchBar.text!.trimmingCharacters(in: CharacterSet.whitespaces)
if searchText.count < 3 {
return
}
self.searchResults.removeAll()
self.tableView.reloadData()
if let document = self.document {
document.cancelFindString()
document.delegate = self
document.beginFindString(searchText, withOptions: .caseInsensitive)
}
}
/// proxy implementation method, can obtain the search results
func didMatchString(_ instance: PDFSelection) {
self.searchResults.append(instance)
self.tableView.reloadData()
}
Copy the code
In the future
Future will continue to add TXT and EPUB format related functions.