176 lines
7.5 KiB
Objective-C
176 lines
7.5 KiB
Objective-C
//
|
|
// WRPageViewController.h
|
|
// WeRead (微信读书)
|
|
//
|
|
// Reverse-engineered header reconstruction.
|
|
// Based on UIPageViewController. Supports UIPageCurl (simulation) and
|
|
// Scroll (slide) page turning styles. Includes fault detection and
|
|
// patching mechanisms for known UIPageViewController bugs.
|
|
//
|
|
|
|
#import <UIKit/UIKit.h>
|
|
|
|
@class WRPageView;
|
|
@class WRChapterData;
|
|
|
|
NS_ASSUME_NONNULL_BEGIN
|
|
|
|
// ============================================================================
|
|
#pragma mark - Page Flipping Style
|
|
// ============================================================================
|
|
|
|
/// The visual style used when transitioning between pages.
|
|
typedef NS_ENUM(NSInteger, WRPageFlippingStyle) {
|
|
WRPageFlippingStyleCurl = 0, // UIPageCurl simulation (paper fold)
|
|
WRPageFlippingStyleSlide = 1, // UIScrollView-based horizontal slide
|
|
WRPageFlippingStyleFade = 2, // Crossfade transition
|
|
WRPageFlippingStyleNone = 3, // Instant switch, no animation
|
|
};
|
|
|
|
// ============================================================================
|
|
#pragma mark - WRPageViewControllerDelegate
|
|
// ============================================================================
|
|
|
|
@protocol WRPageViewControllerDelegate <NSObject>
|
|
@optional
|
|
|
|
/// Called when the page view controller transitions to a new page.
|
|
- (void)pageViewController:(WRPageViewController *)pageViewController
|
|
didFinishAnimating:(BOOL)finished
|
|
previousViewControllers:(NSArray<UIViewController *> *)previousViewControllers
|
|
transitionCompleted:(BOOL)completed;
|
|
|
|
/// Called before a page transition begins.
|
|
- (void)pageViewController:(WRPageViewController *)pageViewController
|
|
willTransitionToViewControllers:(NSArray<UIViewController *> *)pendingViewControllers;
|
|
|
|
/// Called to determine the spine location for interface orientation changes.
|
|
- (UIPageViewControllerSpineLocation)pageViewController:(WRPageViewController *)pageViewController
|
|
spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation;
|
|
|
|
/// Called when the current page index changes.
|
|
- (void)pageViewController:(WRPageViewController *)pageViewController
|
|
didChangePageIndex:(NSUInteger)pageIndex;
|
|
|
|
@end
|
|
|
|
// ============================================================================
|
|
#pragma mark - WRPageViewControllerDataSource
|
|
// ============================================================================
|
|
|
|
@protocol WRPageViewControllerDataSource <NSObject>
|
|
|
|
/// Returns the view controller before the given one (for right-to-left paging).
|
|
- (nullable UIViewController *)pageViewController:(WRPageViewController *)pageViewController
|
|
viewControllerBeforeViewController:(UIViewController *)viewController;
|
|
|
|
/// Returns the view controller after the given one (for left-to-right paging).
|
|
- (nullable UIViewController *)pageViewController:(WRPageViewController *)pageViewController
|
|
viewControllerAfterViewController:(UIViewController *)viewController;
|
|
|
|
@end
|
|
|
|
// ============================================================================
|
|
#pragma mark - WRPageViewController
|
|
// ============================================================================
|
|
|
|
@interface WRPageViewController : UIViewController
|
|
|
|
// ---- Delegates ----
|
|
@property (nonatomic, weak, nullable) id<WRPageViewControllerDelegate> pageDelegate;
|
|
@property (nonatomic, weak, nullable) id<WRPageViewControllerDataSource> pageDataSource;
|
|
|
|
// ---- Configuration ----
|
|
/// The current page flipping style.
|
|
@property (nonatomic, assign) WRPageFlippingStyle pageFlippingStyle;
|
|
|
|
/// Whether the user can interact to change pages.
|
|
@property (nonatomic, assign) BOOL pagingEnabled;
|
|
|
|
/// The underlying UIPageViewController used for page curl and scroll styles.
|
|
@property (nonatomic, strong, readonly) UIPageViewController *uiPageViewController;
|
|
|
|
// ---- State ----
|
|
/// The currently visible page index (0-based within the current chapter).
|
|
@property (nonatomic, assign, readonly) NSUInteger currentPageIndex;
|
|
|
|
/// Whether a page transition is currently in progress.
|
|
@property (nonatomic, assign, readonly) BOOL isTransitioning;
|
|
|
|
// ============================================================================
|
|
#pragma mark - Initialization
|
|
// ============================================================================
|
|
|
|
/// Designated initializer.
|
|
/// @param delegate The page delegate.
|
|
/// @param pageType The UIPageViewControllerTransitionStyle (curl or scroll).
|
|
/// @param flippingStyle The WRPageFlippingStyle to use.
|
|
- (instancetype)initWithDelegate:(id<WRPageViewControllerDelegate>)delegate
|
|
withPageType:(UIPageViewControllerTransitionStyle)pageType
|
|
pageFlippingStyle:(WRPageFlippingStyle)flippingStyle;
|
|
|
|
// ============================================================================
|
|
#pragma mark - Page Navigation
|
|
// ============================================================================
|
|
|
|
/// Sets the current page index, optionally animated.
|
|
- (void)setCurrentPageIndex:(NSUInteger)pageIndex animated:(BOOL)animated;
|
|
|
|
/// Advances to the next page. Returns YES if successful, NO if at the end.
|
|
- (BOOL)goToNextPageAnimated:(BOOL)animated;
|
|
|
|
/// Goes back to the previous page. Returns YES if successful, NO if at the beginning.
|
|
- (BOOL)goToPreviousPageAnimated:(BOOL)animated;
|
|
|
|
/// Replaces the currently displayed view controllers.
|
|
- (void)setViewControllers:(NSArray<UIViewController *> *)viewControllers
|
|
direction:(UIPageViewControllerNavigationDirection)direction
|
|
animated:(BOOL)animated
|
|
completion:(void (^ __nullable)(BOOL finished))completion;
|
|
|
|
// ============================================================================
|
|
#pragma mark - Fault Detection & Patching
|
|
// ============================================================================
|
|
|
|
///
|
|
/// Detects a navigation direction crash in UIPageViewController's
|
|
/// queuingScrollView:didScrollWithAnimation: callback.
|
|
///
|
|
/// This addresses a known Apple bug where the internal
|
|
/// UIPageViewControllerQueuingScrollView can enter an inconsistent state
|
|
/// and crash with an invalid navigation direction.
|
|
///
|
|
/// @param pageVC The UIPageViewController to check.
|
|
/// @param queuingScrollView The internal queuing scroll view (if accessible).
|
|
/// @param methodDidScroll Whether this is called from the didScroll callback.
|
|
/// @param force Force the detection even if already patched.
|
|
/// @param logDetail Whether to log detailed diagnostic info.
|
|
/// @param logCrashReason Whether to log the crash reason string.
|
|
/// @return YES if a fault was detected (and hopefully patched).
|
|
///
|
|
+ (BOOL)detectNavigationDirectionCrashWithPageViewController:(UIPageViewController *)pageVC
|
|
queuingScrollView:(UIScrollView *)queuingScrollView
|
|
inMethodDidScrollWithAnimation:(BOOL)methodDidScroll
|
|
force:(BOOL)force
|
|
logDetail:(BOOL)logDetail
|
|
logCrashReason:(BOOL)logCrashReason;
|
|
|
|
///
|
|
/// Patches the navigation direction fault by swizzling or resetting
|
|
/// the internal state of UIPageViewController.
|
|
+ (void)patchNavigationDirectionFault;
|
|
|
|
///
|
|
/// Patches the "no view controller managing page view" fault.
|
|
/// This occurs when UIPageViewController loses track of its child VCs.
|
|
+ (void)patchNoViewControllerManagingPageViewFault;
|
|
|
|
///
|
|
/// Patches the UIPageCurl animation fault that can cause visual glitches
|
|
/// or crashes during rapid page flipping.
|
|
+ (void)patchUIPageCurlFault;
|
|
|
|
@end
|
|
|
|
NS_ASSUME_NONNULL_END
|