UIPageViewController滑動(dòng)翻頁模式下的問題與解決

一妖碉、場景

最近在做一個(gè)包含閱讀內(nèi)容的項(xiàng)目狞膘,在電子書部分使用了 UIPageViewController 來滿足仿真翻頁與滑動(dòng)翻頁讯蒲,在滑動(dòng)翻頁的過程遇到了各種奇葩的頁號(hào)跳動(dòng)問題掸鹅。

也在百度上找了很多相關(guān)資料童谒,都說它是一個(gè) bug单旁,缺陷。

大部分要么說放棄這個(gè)組件惠啄,使用 UIScraollView 來模擬慎恒。還有一個(gè)解決方案就是使用一段異步重賦值的代碼:

           __block XXViewController *blocksafeSelf = self;

            [self.pageViewController setViewControllers:[NSArray arrayWithObject:[self viewControllerAtIndex:selectIndex]] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:^(BOOL finished) {  //這里的YES是提供一個(gè)動(dòng)畫效果

                if (finished) {

                    dispatch_async(dispatch_get_main_queue(), ^{

                        [blocksafeSelf.pageViewController setViewControllers:[NSArray arrayWithObject:[blocksafeSelf viewControllerAtIndex:selectIndex]] direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL];  //這是實(shí)際起到跳轉(zhuǎn)作用的代碼,animated:NO

                    });

                }

            }];

二撵渡、重新理解代理方法

UIPageViewController 有兩個(gè)前一頁與后一頁的代理方法融柬,在仿真翻頁中可以正確工作。

- (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController;
- (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController;

我以前理解這兩個(gè)方法就當(dāng)前頁的上一頁與下一頁趋距,這種在仿真翻頁中是沒有問題的粒氧,但在滑動(dòng)模式中,這種理解偏差大了节腐。

正確的理解是外盯,上一頁下一頁是相對(duì)于代理方法傳入的那個(gè)視圖控制器而言的,不能直接使用當(dāng)前的章節(jié)與頁數(shù)來計(jì)算翼雀。

三饱苟、解決方案

1、在指定當(dāng)前頁面時(shí)狼渊,不要使用動(dòng)畫模式箱熬。

    [_pageViewController setViewControllers:[self makeCurrentReadViewControllers]
                                  direction:UIPageViewControllerNavigationDirectionForward
                                   animated:NO
                                 completion:nil];

如果使用動(dòng)畫模式,會(huì)導(dǎo)致第一次向左滑動(dòng)的時(shí)候狈邑,重復(fù)顯示第一頁城须。

2、在上一頁與下一頁的代理方法中米苹,使用相對(duì)計(jì)算章節(jié)與頁數(shù)

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
               viewControllerBeforeViewController:(UIViewController *)viewController
{
    _pageChange = _page;
    _chapterChange = _chapter;
    
    if (_isScrollModel) {
        // 非常重要糕伐,否則在滾動(dòng)模式下拿不到正確的頁號(hào),因?yàn)樗⒉皇侵府?dāng)前頁的上一頁
        LSYReadViewController *pageVC = (LSYReadViewController *) viewController;
        _pageChange = pageVC.recordModel.page;
        _chapterChange = pageVC.recordModel.chapter;
    }
    
    // 第一章第一頁沒有前一頁了
    if (_chapterChange == 0 &&_pageChange == 0) {
        // 返回 nil 只會(huì)出現(xiàn)背景蘸嘶,沒有新的vc
        NSLog(@"已經(jīng)是第一頁了A记啤!?鹘稀]喊!");
        return nil;
    }
    

    // 第一頁回去就到了前一章
    if (_pageChange == 0) {
        _chapterChange--;
        LSYChapterModel *chapterModel = _model.chapters[_chapterChange]; // 前一章的model
        chapterModel.isReady = YES;
        _pageChange = chapterModel.pageCount - 1;// 頁號(hào)為前一章的最大頁數(shù)
    } else{
        // 否則正常的減一頁
        _pageChange--;
    }
    
    return [self readViewWithChapter:_chapterChange page:_pageChange];
}
// 后一頁
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
                viewControllerAfterViewController:(UIViewController *)viewController
{
    // 當(dāng)前章節(jié)與頁號(hào)
    _pageChange = _page;
    _chapterChange = _chapter;
    
    if (_isScrollModel) {
        // 非常重要雪情,否則在滾動(dòng)模式下拿不到正確的頁號(hào),因?yàn)樗⒉皇侵府?dāng)前頁的下一頁
        LSYReadViewController *pageVC = (LSYReadViewController *) viewController;
        _pageChange = pageVC.recordModel.page;
        _chapterChange = pageVC.recordModel.chapter;
    }
    
    // 如果到了最后一章的最后一頁你辣,返回nil
    if (_chapterChange == _model.chapters.count - 1 &&
        _pageChange == _model.chapters.lastObject.pageCount - 1
        ) {
        return nil;
    }
    // 下一章
    LSYChapterModel *chapterModel = _model.chapters[_chapterChange];
    chapterModel.isReady = YES;
    if (_pageChange == chapterModel.pageCount - 1) {
        _chapterChange += 1;
        _pageChange = 0;
    } else {
        // 本章下一節(jié)
        _pageChange += 1;
    }

    return [self readViewWithChapter:_chapterChange page:_pageChange];
}

四巡通、手動(dòng)翻頁

完成點(diǎn)擊左右頁面自動(dòng)滑動(dòng)翻頁

// 動(dòng)畫向前翻頁
- (void)moveToPrevPage
{
    UIViewController *vc = [self pageViewController:self.pageViewController
                 viewControllerBeforeViewController:self.pageViewController.viewControllers.firstObject];
    if (vc == nil) {
        return;
    }
    __weak typeof(self) weakself = self;
    [_pageViewController setViewControllers:@[vc]
                                  direction:UIPageViewControllerNavigationDirectionReverse
                                   animated:YES // 滑動(dòng)
                                 completion:^(BOOL finished) {
                                     if (finished) {
                                         //  完成后要重置一下尘执,避免有 bug
                                         dispatch_async(dispatch_get_main_queue(), ^{
                                             [weakself.pageViewController
                                                  setViewControllers:@[vc]
                                                  direction:UIPageViewControllerNavigationDirectionReverse
                                                  animated:NO
                                                  completion:NULL];
                                         });
                                     }
                                 }];
}

五、總結(jié)

這個(gè)組件其實(shí)是沒有 bug 的宴凉,按蘋果嚴(yán)謹(jǐn)?shù)娘L(fēng)格來說誊锭,這個(gè)類似問題出現(xiàn)在 iOS6的時(shí)候就有人提出來了,如果是問題弥锄,早就修復(fù)了丧靡。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市籽暇,隨后出現(xiàn)的幾起案子温治,更是在濱河造成了極大的恐慌,老刑警劉巖戒悠,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件熬荆,死亡現(xiàn)場離奇詭異,居然都是意外死亡绸狐,警方通過查閱死者的電腦和手機(jī)卤恳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寒矿,“玉大人突琳,你說我怎么就攤上這事》啵” “怎么了拆融?”我有些...
    開封第一講書人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長主巍。 經(jīng)常有香客問我冠息,道長,這世上最難降的妖魔是什么孕索? 我笑而不...
    開封第一講書人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任逛艰,我火速辦了婚禮,結(jié)果婚禮上搞旭,老公的妹妹穿的比我還像新娘散怖。我一直安慰自己,他們只是感情好肄渗,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開白布镇眷。 她就那樣靜靜地躺著,像睡著了一般翎嫡。 火紅的嫁衣襯著肌膚如雪欠动。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音具伍,去河邊找鬼翅雏。 笑死,一個(gè)胖子當(dāng)著我的面吹牛人芽,可吹牛的內(nèi)容都是我干的望几。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼萤厅,長吁一口氣:“原來是場噩夢啊……” “哼橄抹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起惕味,我...
    開封第一講書人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤楼誓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后赦拘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體慌随,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年躺同,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了阁猜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蹋艺,死狀恐怖剃袍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情捎谨,我是刑警寧澤民效,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站涛救,受9級(jí)特大地震影響畏邢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜检吆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一舒萎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蹭沛,春花似錦臂寝、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至帚呼,卻和暖如春掏缎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來泰國打工御毅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留根欧,地道東北人怜珍。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓端蛆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親酥泛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子今豆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容