Главная » Хабрахабр » [Перевод] Создаем читалку eBook с помощью PDFKit на Swift

[Перевод] Создаем читалку eBook с помощью PDFKit на Swift

Добрый день! Представляю вашему вниманию продолжение статьи «Скачиваем, сохраняем и просматриваем PDF в Swift», как и обещал автор — немного подробнее рассмотрим PDFKit.

PDFKit появился в iOS 11, и в нем есть 3 замечательные функции, о которых бы я хотел рассказать, в процессе создания приложения читалки eBook: Разбиение по страницам, Отображение Содержания и Иконка страницы.

Всем, кто заинтересовался, добро пожаловать под кат.
image

image

image
Paging, Outline, и Thumbnails

Создание PDFViewController при помощи Initializer Injection

Именно поэтому я выбрал Initializer Injection, а не Property Injection или Method Injection. При создании переменной URL в PDFViewController, мы сделали её неизменяемой.

Единственная внедряемая переменная, это pdfUrl, а остальные: document и outline, доступны через область локального класса и могут быть инициированы через init().

Содержимое pdfView у нас не меняется, поэтому я обозначил его переменной document и так же инициализировал через init().

import UIKit
import PDFKit class PDFViewController: UIViewController ... override func viewDidLoad() { super.viewDidLoad() view.addSubview(pdfView) }
}

import UIKit class ViewController: UIViewController { @IBAction func openPdfPressed(_ sender: Any) { guard let path = Bundle.main.url(forResource: "swift", withExtension: "pdf") else { print("failed to unwrap fileURL") return } let pdfViewController = PDFViewController(pdfUrl: path) present(pdfViewController, animated: true, completion: nil) } }

Устанавливаем горизонтальное разбиение по страницам

Для того, чтобы сделать горизонтальный скролл, как в книге, нужно добавить несколько настроек в PDFView. Теперь у нас есть содержимое в документе, которое мы прописали в pdfView.document.

private func setupPDFView() { view.addSubview(pdfView) pdfView.displayDirection = .horizontal pdfView.usePageViewController(true) pdfView.pageBreakMargins = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) pdfView.autoScales = true
}

image

Иконки страниц для удобной навигации

Все, что нужно сделать — это назначить наш pdfView свойству thumbnailView.pdfView. В PDFKit есть потрясающе удобная вещь, такая как ThumbnailView. Никаких делегатов, уведомлений и других настроек. И все!

private func setupThumbnailView() { thumbnailView.pdfView = pdfView thumbnailView.backgroundColor = UIColor(displayP3Red: 179/255, green: 179/255, blue: 179/255, alpha: 0.5) thumbnailView.layoutMode = .horizontal thumbnailView.thumbnailSize = CGSize(width: 80, height: 100) thumbnailView.contentInset = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10) view.addSubview(thumbnailView)
}

image

Отображение содержания для навигации по главам

Значит нам надо углубиться в иерархию содержания (outline) в документе (document) чтобы попасть на нужную страницу (page). Чтобы попасть на определенную страницу, нам нужно передать в pdfView конкретную страницу (PDFPage).

image

Поэтому мне надо: Я использую UITableViewController как всплывающее окно (popOver).

  1. Создать протокол. UITableViewController должен следовать этому протоколу.
  2. Добавить некоторые методы делегата чтобы получить доступ к pdfView в PDFViewController.
  3. Вызвать метод делегата когда пользователь выберет определенную ячейку.

import UIKit
import PDFKit protocol OutlineDelegate: class { func goTo(page: PDFPage)
} class OutlineTableViewController: UITableViewController { let outline: PDFOutline weak var delegate: OutlineDelegate? init(outline: PDFOutline, delegate: OutlineDelegate?) { self.outline = outline self.delegate = delegate super.init(nibName: nil, bundle: nil) } ... override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return outline.numberOfChildren } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as UITableViewCell if let label = cell.textLabel, let title = outline.child(at: indexPath.row)?.label { label.text = String(title) } return cell } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if let page = outline.child(at: indexPath.row)?.destination?.page { delegate?.goTo(page: page) } } }

image

Вот мы и применили 3 основные функции PDFKit. Ура! Проект доступен по ссылке всем желающим. Есть еще некоторые тривиальные детали интерфейса, но в данной статье мы не будем на них фокусироваться.


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Теория счастья. Случайности неслучайны

Продолжаю знакомить читателей Хабра с главами из своей книжки «Теория счастья» с подзаголовком «Математические основы законов подлости». Это ещё не изданная научно-популярная книжка, очень неформально рассказывающая о том, как математика позволяет с новой степенью осознанности взглянуть на мир и жизнь ...

Снежинки в стилистике StarWars своими руками (upd. 2018)

Для изготовления снежинок вам потребуется: Файл со схемой.2. 1. Ножницы.4. Принтер (думаю лазерный будет предпочтительней).3. Бумага.5. Скальпель.5. Лично мое мнение — при печати на стандартной офисной бумаге плотностью 80г/м2 становится не очень удобно вырезать (все-таки при складывании бумаги получается толстый ...