仿映客刷禮物效果---代碼優化

上一篇文章《仿映客刷禮物效果---基本邏輯實現》中,分析了刷禮物效果的基本流程與具體實現代碼。但還有一些BUG和一些可優化的地方沒有處理,現在我們就來分析下這些遺留的問題。當然個人的能力是有限的,肯定還有很多我沒有發現到的問題,如果大家在使用過程中有遇到其它的問題,歡迎大家及時指出,我好及時完善。

優化后的效果圖如下:


效果圖.png

廢話不多說,先看問題。

問題一

問題描述

問題效果圖如下圖:


問題一.gif

從圖中可以看到:當一個禮物動畫組正在執行隱藏動畫時,這時恰好收到一個新的與之相同類型的禮物消息,按正常邏輯來看,這個新的禮物消息應該應該作為一個新的動畫組開始展示。但是,從GIF圖中可以看到,連送按鈕再次出現的時,新的動畫組并沒有開始展示,那新接收到禮物消息去哪里了呢?

問題原因

如果將隱藏動畫的動畫時間設置長一點,重復上面的問題流程。你就會發現,其實新接收到的禮物消息并不是消失了,而是被判定為一次連乘動畫。所以這時其實是一邊執行隱藏動畫,一遍執行連乘動畫,這就導致連乘動畫很難被看到,從而造成了新接收到的禮物消息消失了。

問題解決

知道了問題原因,解決問題就非常簡單了。這里我的解決方法是:讓cell在執行隱藏動畫時不被判定為正在執行動畫,因此我給cell設置了幾種動畫狀態,其邏輯關系如下圖所示:


動畫狀態邏輯.png

有了動畫狀態之后,只用修改動畫檢測的判斷條件就可以了,修改后的代碼如下:

- (PresentViewCell *)examinePresentingCell:(id<PresentModelAble>)obj
{
    for (PresentViewCell *cell in self.showCells) {
        if ([cell.sender isEqualToString:[obj sender]] && [cell.giftName isEqualToString:[obj giftName]]) {
            //當前正在展示動畫并且不是隱藏動畫
            if (cell.state != AnimationStateNone && cell.state != AnimationStateHiding) return cell;
        }
    }
    return nil;
}

如果當前沒有不為空閑并且也沒有在隱藏動畫,就判定當前cell可以執行連乘動畫。
運行程序,再次測試,就會發現當cell正在執行隱藏動畫時收到一條相同類型消息,新的消息會在新的動畫組中展示,或是等有了空閑的cell時在展示。(修改后的具體效果可以在Demo中驗證,下同)

問題二

問題描述

問題效果圖如下:


問題二.gif

從圖中可以看到:當連續多次快速的點擊同一個發送按鈕時,連乘的動畫效果就消失了。

問題原因

很明顯這里的問題原因就是因為:上一次點擊的連乘動畫還沒執行完,就開始了下一次連乘動畫,從而造成了這種效果。

問題解決

從問題原因中很容易想到這里需要用到緩存機制,即等到上一次動畫執行完了再執行下一次動畫。首先我們很容易想到的就是NSOperationQueue和dispatch_group_t,這是系統封裝的兩個任務隊列,很容易實現上面的需求,而且還特別簡單,只用在shakeAnimationWithNumber:里面實現緩存機制就行了。這里介紹下dispatch_group_t隊列的實現方法,其代碼如下:

- (void)shakeAnimationWithNumber:(NSInteger)number
{
    if (!_queue && !_group) {
        _queue = dispatch_queue_create("com.shakeCache.queue", DISPATCH_QUEUE_SERIAL);
        _group = dispatch_group_create();
        dispatch_group_notify(_group, dispatch_get_main_queue(), ^{
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [self hiddenAnimationOfShowShake:YES];
            });
        });
    }
    dispatch_group_async(_group, _queue, ^{
        [self startShakeAnimationWithNumber:number completion:nil];
    });
}

代碼很簡單,就是創建一個全局的串行隊列,如果group任務完成就延時執行隱藏動畫,每次調用都想group中添加一個連乘動畫任務。
運行程序,你會發現問題還是存在,這是為什么呢?其實原因很簡單,就是因為:UIView封裝的動畫是在子線程中執行,與添加任務操作不在同一個線程中。所以雖然任務是順序添加的,但動畫的執行并不是串行執行的。
這里的解決辦法是:自己實現緩存--收到連乘動畫先緩存,如果有緩存并且沒有正在執行連乘動畫,就取緩存,開始動畫,動畫完成就刪除緩存,再去取緩存,只到沒有緩存為止。具體實現代碼如下:

- (void)shakeAnimationWithNumber:(NSInteger)number
{
    if (number > 0) [self.caches addObject:@(number)];
    if (self.caches.count > 0 && _state != AnimationStateShaking) {
        NSInteger cache        = [self.caches.firstObject integerValue];
        [self.caches removeObjectAtIndex:0];//不能刪除對象,因為可能有相同的對象
        __weak typeof(self) ws = self;
        [self startShakeAnimationWithNumber:cache completion:^(BOOL finished) {
            [ws shakeAnimationWithNumber:-1];//傳-1是為了緩存不被重復添加
        }];
    }
}

再次運行程序,就會發現連乘動畫是串行執行了。

問題三

問題描述

在開始下一次動畫去緩存時,這時剛好收到一個與取出的緩存相同類型的消息,又會去取緩存。在極端的情況下,這會造成兩個相同類型的禮物動畫同時展示。
因為這是一個邏輯上特別極端的情況,所以這里沒有給出效果圖。

問題原因

這個問題原因其實就是因為:取緩存到動畫開始這段時間內收到一條與取出緩存相同類型的消息,導致這個新的消息在做動畫檢測時沒有檢測出來,所以新的消息可能也會作為新的動畫組開始展示。

問題解決

這里的解決辦法是將取緩存到動畫開始這個時間縮減到最短,也就是在開始展示動畫前就將cell的動畫狀態從AnimationStateNone設置成AnimationStateShowing。
關于這個問題,有興趣的可以自行測試,測試時記得要增大取緩存到開始動畫這段時間。具體操作就是:增大cell的顯示動畫時間,并且等cell的顯示動畫完成再將cell的動畫狀態從AnimationStateNone設置成AnimationStateShowing。(如果有測試出問題的,記得將問題效果的gif圖分享給我!拜謝了!)

問題四

解決一個問題,就會帶來新的問題。這里給動畫做了這么多的緩存之后帶來的新的問題是什么呢!想必測試過的應該已經發現了:連送按鈕已經隱藏了,但是連乘動畫還在執行,這肯定是不合邏輯的。

對于這個問題,只有在項目中有要求出現連送按鈕才會出現,而且出現了也不一定算是問題(映客也沒解決這個問題),所以這里就不解決這個問題了,如果確實有要求的,這里提供下思路:因為展示動畫和連乘動畫的動畫時間都是確定的,所以很容易計算出執行完當前動畫組需要的時間。然后每接收到一個連乘動畫就對這個時間進行更新,并用代理或其它的形式將這個時間值傳遞出去,最后根據這個值對連送按鈕進行控制就可以了。(當然了,有實現了這個思路或是有更好思路的,方便的話,也請分享給我,再次拜謝了!)

一個好的功能應該除了具有易用性之外,還應該具有良好的擴展性。

擴展

因為項目的需求不同,所以對展示動畫與隱藏動畫的要求也各部相同。這里就提供了對這連個動畫自定義的接口,接口名如下:

/**
 *  自定義展示動畫
 *
 *  @param flag 是否帶有連乘動畫
 */
- (void)customDisplayAnimationOfShowShakeAnimation:(BOOL)flag;
/**
 *  自定義隱藏動畫
 *
 *  @param flag 是否帶有連乘動畫
 */
- (void)customHideAnimationOfShowShakeAnimation:(BOOL)flag;

如果想對這兩動畫進行簡單的自定義,就可以在自定義cell中重寫這兩方法。需要注意的是,這兩方法是在UIView封裝的動畫的animations回調中調用,所以只用修改cell的frame就夠了。

一般項目中通過這種方法自定義cell的展示和隱藏動畫就可以滿足需求,如果項目中確實需要更絢麗的動畫效果,就需要修改PrentViewCell的showAnimationWithModel:showShakeAnimation:prepare:completion:方法和hiddenAnimationOfShowShake:方法中的動畫代碼。

當然,還有其它的地方可以擴展,例如:讓禮物消息只在指定的cell上展示,如VIP用戶發送的禮物消息,在特定的位置上展示;還可以對消息的展示優先級進行區分,如不同等級的用戶展示消息的優先級就不一樣,等等這些都是有可能項目需要的需求。這里就不一一對這些需求進行實現了,關于優化后的Demo,大家可以點擊這里下載。

最后,還是開篇那句話:個人的能力有限,肯定還有很多我沒有發現到的問題,如果大家在使用過程中有遇到其它的問題,歡迎大家及時指出,我好及時完善。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,117評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,860評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,128評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,291評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,025評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,421評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,477評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,642評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,177評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,970評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,157評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,717評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,410評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,821評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,053評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,896評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,157評論 2 375

推薦閱讀更多精彩內容

  • 最近做了個直播項目,需要用到彈幕和刷禮物。在網上找了許多開源代碼,發現都不是很適合自己的項目需求,于是利用空余時間...
    Rasping閱讀 4,710評論 23 40
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,156評論 4 61
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,682評論 25 708
  • 記憶已經模糊了太多太多,因為想不起的東西,就那么一直被遺忘了,故事的開始和結束都不再是故事的重點了,享受的只是過程...
    一空一白閱讀 140評論 0 0