ios之UITableView如何優(yōu)雅的插入數據: 旋轉180°下拉加載cell頂置

一. 概述

一般項目里面用到UITableView的概率還是灰常大的, 我的項目從一開始也用了. 大概的來說就是類似一個收件箱的功能, 推送來一條消息就加一個cell, 這是很簡單的. 藍鵝, 接下來經歷了兩次需求更改:

1. 增加'數據本地化'的功能;
2. 增加查看歷史消息功能, 也就是下拉加載更多的消息.

第一個還好說, 就是用FMDB弄了個簡單的數據庫, 差不多就是獲取數據的途徑變成從數據庫獲取而已;
在增加了第一個需求之后, 疊加提出第二個需求, 看起來也很簡單哦, 不就是加數據嘛. 但是, 當我開始做起來的時候才發(fā)現, 坑蠻多的.

這篇文章是基于我自己項目所寫的, 可能在一些地方處理比較特殊并不具備"普世價值"; 但從開發(fā)者學習的角度來說, 我始終認為思路比代碼重要. 所以這里我可能在思路方面比較啰嗦點, 直接要代碼的慎重選擇啊.
先說一下, 需求二里面主要遇到的坑有兩個:

坑一 : 下拉加載的10條消息, 顯示直接在第0-4條, 要看第5-9條的話又得反方向上滑

為了解決坑一, 將tableview和cell都旋轉了180°, 這時候, 坑二來了

坑二 : 在初始cell數量較少的時候, 推送新消息過來增加cell的時候導致界面跳動

二. 項目過程

2.1需求分析
由于第一個需求太過簡單, 所以就忽略啦. 這里直接講第二個需求的.
剛剛上面講的不是很清楚, 這里補充一下第二個需求的具體:

1.進入到界面的時候, 里面要先顯示最多10條消息;
2.下拉可以加載歷史數據(每次10條);
3.當有新消息推送過來的時候, 要添加在最底部, 并滾動到最底部;
4.三日內做完.

剛看到這個需求的時候, 我的第一個反應是這太TM簡單了, too simple! 看老夫如何在三天時間以內用半天做完再用兩天半假裝沒做(tou)完(lan)????.
2.2 坑一
藍鵝, 忙活半天過后, 我發(fā)現自己too young too naive????. 這就是上面說的坑一, 圖是這樣的, 可以看到點擊"消息+1"的時候還算正常, 但是下拉加載更多消息(10條)的時候, 都是停留在最頂部, 也就是上面坑一說的, 要看第5-9條的時候, 得反方向上滑

正常的.gif

為了解決坑一, 我嘗試過調試NSIndexPath并且使用scrollToRowAtIndexPath:<#(nonnull NSIndexPath *)#> atScrollPosition:<#(UITableViewScrollPosition)#> animated:<#(BOOL)#>]方法來各種折騰....再過了半天之后????放棄了, 下班, 對, 下班!!!誰說程序猿都得加班的????.

2.3 坑二
昨晚想了一(yi)下(晚)和簡單的實踐(說好的不加班呢, 變相加班????!), 發(fā)現在uitableview的底部使用inset...和scroll...方法拼接數據很完美, 腦洞大開," 獨創(chuàng)"(后來發(fā)現網上也有)ios大法之乾坤大挪移----將整個tableview旋轉180°!!!!! 當然cell也要旋轉180°.
旋轉的代碼分別是:

    CGAffineTransform transform =CGAffineTransformMakeRotation(M_PI);
    [tbV setTransform:transform];

cell的旋轉:

        CGAffineTransform transform =CGAffineTransformMakeRotation(M_PI);
        [self.contentView setTransform:transform];

當然, 使用mjrefresh的話, 就得用原來使用的mj_header換成mj_footer了(關于mjrefresh的使用).

弄好之后是這樣的, cell直接在最底部:


倒過來一.gif

這明顯是不行的, 為了使得cell數量比較少的時候可以頂置(實際是底置, 因為tableview旋轉了180°了), 于是想到了根據tableView.contentSize.height(關于 tableView.contentSize你想了解的)來設置tableView.contentInset, 代碼是這樣的

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{

    if (tableView.contentSize.height < tableView.frame.size.height)
    {
        
        tableView.contentInset = UIEdgeInsetsMake(tableView.frame.size.height - tableView.contentSize.height - RSRealValue(120), 0, 0, 0);
    }
}

運行出來一看, 哇, 完美解決!!!! 藍鵝, 高興地太早了????. 這時候下拉加載時沒問題的, 但新加一條消息的時候, 新的cell會把原來的cell頂上去, 而不是拼接在最下面, 如圖:

倒過來contentInset.gif

經過一番思考, 本人大致的認為, 在新加入cell的時候, 原來的tableView.contentSize還是沒變, 也就是說tableView.contentSize的布局其實還是只到了上一個cell的底部, 并以此往復, 所以出現了上圖里面加了3條新消息再下滑的時候才出現????.
這時候, 又想到了一個方法, 可以嘗試監(jiān)聽tableView.contentSize還動態(tài)修改tableView.contentSize.....&%$#@!@#$%&%$過程省略幾百字, 直接說結果吧, 然并卵. 而且, 在ios的UITableView里面, 并不是很推薦修改tableView.contentSize, 因為這個是蘋果自身維持動態(tài)平衡的, 我們強心修改的話會影響其平衡, 而且在控制臺會出現警報. 所以很不推薦.
就這樣又折騰了半天.....下午整個人都在想這個問題. 終于在吃了一顆糖果之后, 想到一個方法:
為啥不通過記錄cell的總高度來代替tableView.contentSize, 然后設置一個透明的tableheaderview來代替設置tableView.contentInset??????快被自己的機智感動了????.
這樣既可以繞過上面說的問題了. 說干就干.
需要在cell的model文件里面增加一個記錄本cell高度的屬性:

// 計算出來的cell的高度
@property (nonatomic, assign) CGFloat cellHeight;

同時, 也得在控制器文件里面增加一個記錄所有cell總高度的屬性:

// cell的疊加高度
@property (nonatomic, assign) CGFloat cellsTotalHeight;

并且寫了它的懶加載方法, 這樣每次在獲取總高度的時候都能保證是最新的

- (CGFloat)cellsTotalHeight{
    
    CGFloat heightAll = 0;

    for (int i = 0; i < self.dataMulArr.count; i ++) {
        
        OneModel *model = self.dataMulArr[i];
        
        heightAll = heightAll + model.cellHeight;
    }
    
    _cellsTotalHeight = heightAll;
    
    NSLog(@"cell總高度: %f",heightAll);
    
    return heightAll;
}

同時, 返回頭部視圖和高度是這樣de(為了方便調試, 先把頭部視圖設置成有個半透明色)

#pragma mark- 返回頭部視圖
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{

    UIView *headV = [[UIView alloc] init];
//    headV.backgroundColor = [UIColor clearColor];
    headV.backgroundColor = RSColorFromRGBA(0x00FF00, 0.5);
    return headV;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
    
    NSLog(@"頭部視圖高度中cell: %f", self.cellsTotalHeight);
    
    CGFloat headHeight = 0;
    
    if (self.cellsTotalHeight < self.tbV.frame.size.height)
    {
        
        headHeight = self.tbV.frame.size.height - self.cellsTotalHeight - RSRealValue(240);
    }

    return headHeight;
    
}

跑出來是這樣的:


倒過來加header.gif

這時候再把tableheaderview的背景色改成透明的, 就成了這樣了:


倒過來加header透明.gif

果然完美解決了????, 這時候其實只剩一天時間假裝沒完(偷)成(lan)了.

不過還是要注意一下, 看圖倒過來加header.gif將tableheaderview改成透明之后, 新增cell還是會被tableheaderview擋住, 所以最后一個cell是點擊不到的. 因為我項目里面的cell不需要點擊, 所以這個問題我可以忽略; 如果小伙伴項目里面的cell需要點擊的話, 就要將tableheaderview高度進一步減去新增cell的高度哦. 這里我就不做具體代碼了, 小伙伴們自己探索一下把.

三. 小總結

總結起來, 這里面幾個關鍵點是:

1.旋轉180°
2.不使用reloaddata方法, 而是使用inser....和scroll...兩個方法
3.通過增加tableheaderview來實現倒轉tableview之后cell的頂置, 并且動態(tài)的改變tableheaderview的高度.

這個雖然只是項目的一小部分, 但每次解決問題之后都能獲得成就感, 這就是碼農單純的快樂吧.

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

推薦閱讀更多精彩內容

  • 概述在iOS開發(fā)中UITableView可以說是使用最廣泛的控件,我們平時使用的軟件中到處都可以看到它的影子,類似...
    liudhkk閱讀 9,079評論 3 38
  • 發(fā)現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,143評論 4 61
  • 1.badgeVaule氣泡提示 2.git終端命令方法> pwd查看全部 >cd>ls >之后桌面找到文件夾內容...
    i得深刻方得S閱讀 4,697評論 1 9
  • 本周關鍵字:找回節(jié)奏 九十天目標檢視:九十天相約 1,斷舍離,建立空間力及信息力。整理完印象筆記,把印象筆記框架與...
    葉子佟閱讀 370評論 0 0
  • 喜歡漫畫。尤其愛這些清簡的素描畫。每次看到漫畫,總能呆呆想半天。小小一幅畫中,寥寥幾筆,卻蘊藏著豐盈無比的世界。 ...
    侯玲玉閱讀 552評論 0 4