Skip to content

Commit 9dc13a0

Browse files
authored
Improve reliability of EPUB pagination view (#550)
1 parent d805e4e commit 9dc13a0

File tree

1 file changed

+43
-14
lines changed

1 file changed

+43
-14
lines changed

Sources/Navigator/EPUB/EPUBNavigatorViewController.swift

+43-14
Original file line numberDiff line numberDiff line change
@@ -346,9 +346,9 @@ open class EPUBNavigatorViewController: UIViewController,
346346
hasPositions: !positionsByReadingOrder.isEmpty
347347
)
348348

349-
paginationView.frame = view.bounds
350-
paginationView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
351-
view.addSubview(paginationView)
349+
paginationView!.frame = view.bounds
350+
paginationView!.autoresizingMask = [.flexibleHeight, .flexibleWidth]
351+
view.addSubview(paginationView!)
352352

353353
applySettings()
354354

@@ -481,7 +481,10 @@ open class EPUBNavigatorViewController: UIViewController,
481481

482482
/// Goes to the next or previous page in the given scroll direction.
483483
private func go(to direction: EPUBSpreadView.Direction, options: NavigatorGoOptions) async -> Bool {
484-
guard on(.move(direction)) else {
484+
guard
485+
let paginationView = paginationView,
486+
on(.move(direction))
487+
else {
485488
return false
486489
}
487490

@@ -515,7 +518,7 @@ open class EPUBNavigatorViewController: UIViewController,
515518

516519
// MARK: - Pagination and spreads
517520

518-
private var paginationView: PaginationView!
521+
private var paginationView: PaginationView?
519522

520523
private func makePaginationView(hasPositions: Bool) -> PaginationView {
521524
let view = PaginationView(
@@ -529,11 +532,20 @@ open class EPUBNavigatorViewController: UIViewController,
529532
return view
530533
}
531534

535+
private func invalidatePaginationView() async {
536+
guard let paginationView = paginationView else {
537+
return
538+
}
539+
540+
paginationView.isScrollEnabled = isPaginationViewScrollingEnabled
541+
await reloadSpreads(force: true)
542+
}
543+
532544
private var spreads: [EPUBSpread] = []
533545

534546
/// Index of the currently visible spread.
535547
private var currentSpreadIndex: Int {
536-
paginationView.currentIndex
548+
paginationView?.currentIndex ?? 0
537549
}
538550

539551
// Reading order index of the left-most resource in the visible spread.
@@ -575,6 +587,7 @@ open class EPUBNavigatorViewController: UIViewController,
575587
let locator = locator ?? currentLocation
576588

577589
guard
590+
let paginationView = paginationView,
578591
// Already loaded with the expected amount of spreads?
579592
force || spreads.first?.spread != viewModel.spreadEnabled,
580593
on(.load(locator))
@@ -607,7 +620,7 @@ open class EPUBNavigatorViewController: UIViewController,
607620
}
608621

609622
private func loadedSpreadViewForHREF<T: URLConvertible>(_ href: T) -> EPUBSpreadView? {
610-
paginationView.loadedViews
623+
paginationView?.loadedViews
611624
.compactMap { _, view in view as? EPUBSpreadView }
612625
.first { $0.spread.links.firstWithHREF(href) != nil }
613626
}
@@ -640,7 +653,7 @@ open class EPUBNavigatorViewController: UIViewController,
640653
return pendingLocator
641654
}
642655

643-
guard let spreadView = paginationView.currentView as? EPUBSpreadView else {
656+
guard let spreadView = paginationView?.currentView as? EPUBSpreadView else {
644657
return nil
645658
}
646659

@@ -670,7 +683,7 @@ open class EPUBNavigatorViewController: UIViewController,
670683
}
671684

672685
public func firstVisibleElementLocator() async -> Locator? {
673-
guard let spreadView = paginationView.currentView as? EPUBSpreadView else {
686+
guard let spreadView = paginationView?.currentView as? EPUBSpreadView else {
674687
return nil
675688
}
676689
return await spreadView.findFirstVisibleElementLocator()
@@ -705,6 +718,7 @@ open class EPUBNavigatorViewController: UIViewController,
705718
let locator = publication.normalizeLocator(locator)
706719

707720
guard
721+
let paginationView = paginationView,
708722
let spreadIndex = spreads.firstIndexWithHREF(locator.href),
709723
on(.jump(locator))
710724
else {
@@ -759,6 +773,10 @@ open class EPUBNavigatorViewController: UIViewController,
759773
}
760774

761775
public func clearSelection() {
776+
guard let paginationView = paginationView else {
777+
return
778+
}
779+
762780
for (_, pageView) in paginationView.loadedViews {
763781
(pageView as? EPUBSpreadView)?.webView.clearSelection()
764782
}
@@ -779,6 +797,10 @@ open class EPUBNavigatorViewController: UIViewController,
779797
Task {
780798
await initialized()
781799

800+
guard let paginationView = paginationView else {
801+
return
802+
}
803+
782804
await withTaskGroup(of: Void.self) { tasks in
783805
let source = self.decorations[group] ?? []
784806
let target = decorations.map {
@@ -821,6 +843,10 @@ open class EPUBNavigatorViewController: UIViewController,
821843
Task {
822844
await initialized()
823845

846+
guard let paginationView = paginationView else {
847+
return
848+
}
849+
824850
await withTaskGroup(of: Void.self) { tasks in
825851
for (_, view) in paginationView.loadedViews {
826852
tasks.addTask {
@@ -854,7 +880,7 @@ open class EPUBNavigatorViewController: UIViewController,
854880
}
855881

856882
view.backgroundColor = settings.effectiveBackgroundColor.uiColor
857-
paginationView.isScrollEnabled = isPaginationViewScrollingEnabled
883+
paginationView?.isScrollEnabled = isPaginationViewScrollingEnabled
858884
}
859885

860886
// MARK: - User interactions
@@ -872,7 +898,7 @@ open class EPUBNavigatorViewController: UIViewController,
872898
/// Evaluates the given JavaScript on the currently visible HTML resource.
873899
@discardableResult
874900
public func evaluateJavaScript(_ script: String) async -> Result<Any, Error> {
875-
guard let spreadView = paginationView.currentView as? EPUBSpreadView else {
901+
guard let spreadView = paginationView?.currentView as? EPUBSpreadView else {
876902
return .failure(EPUBError.spreadNotLoaded)
877903
}
878904
return await spreadView.evaluateScript(script)
@@ -913,15 +939,18 @@ open class EPUBNavigatorViewController: UIViewController,
913939
extension EPUBNavigatorViewController: EPUBNavigatorViewModelDelegate {
914940
func epubNavigatorViewModelInvalidatePaginationView(_ viewModel: EPUBNavigatorViewModel) {
915941
Task {
916-
paginationView.isScrollEnabled = isPaginationViewScrollingEnabled
917-
await reloadSpreads(force: true)
942+
await invalidatePaginationView()
918943
}
919944
}
920945

921946
func epubNavigatorViewModel(_ viewModel: EPUBNavigatorViewModel, runScript script: String, in scope: EPUBScriptScope) {
922947
Task {
923948
await initialized()
924949

950+
guard let paginationView = paginationView else {
951+
return
952+
}
953+
925954
switch scope {
926955
case .currentResource:
927956
await (paginationView.currentView as? EPUBSpreadView)?.evaluateScript(script)
@@ -1159,7 +1188,7 @@ extension EPUBNavigatorViewController: EPUBSpreadViewDelegate {
11591188
}
11601189

11611190
func spreadViewPagesDidChange(_ spreadView: EPUBSpreadView) {
1162-
if paginationView.currentView == spreadView {
1191+
if paginationView?.currentView == spreadView {
11631192
updateCurrentLocation()
11641193
}
11651194
}

0 commit comments

Comments
 (0)