iOS 中 UITableView 某個場景的使用

最近在想關(guān)于 UITableView 的一些事,對于界面搭建來說栏饮,它是再常用不過了吧兔,對于它可以說的事,實(shí)在是太多了袍嬉,然而我這兩天想的是應(yīng)用場景的一些情形境蔼,其中有一些疑問。

多種樣式伺通,多種點(diǎn)擊的列表
  • 1箍土、多種點(diǎn)擊的列表,假如還是傳統(tǒng)方式泵殴,那么判斷是否太多了一點(diǎn)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    switch (indexPath.row) {
        case 0: {
            
        }
            break;
        default:
            break;
    }
}

  • 2涮帘、多種樣式的列表,用一個 UITableViewCell 肯定是不行的
    此時(shí)肯定是多個 Cell 笑诅,甚至有種感覺此時(shí)不如直接用 UIButton 是否都會更方便一些调缨,更好擴(kuò)展一些呢疮鲫?

  • 3、另外例如淘寶首頁這種界面弦叶,此時(shí)又該怎么辦呢俊犯?

復(fù)雜的 Home 界面

當(dāng)然據(jù)說他們是采取了他們自己的 ListView, 此處不做討論,只是假如我們自己要實(shí)現(xiàn)的情況下伤哺,又應(yīng)該怎么辦呢燕侠?

我想我的實(shí)現(xiàn)首先肯定是整體的 UICollectionView + HeaderView, 而此處復(fù)雜的是 HeaderView, 高度和滑動的實(shí)現(xiàn),所以此處還是可以考慮到 UITableView 的立莉,當(dāng)然是特殊的 UITableView绢彤。


一、小嘗試蜓耻,解決多種點(diǎn)擊(樣式相同)

之前我們在做個人頁面的時(shí)候茫舶,就是如上圖微信中的個人頁面一樣,樣式相同有多種點(diǎn)擊 刹淌,我們之前組長封裝了一個方便點(diǎn)擊饶氏,樣式可調(diào)的工具。

  • 數(shù)據(jù)處理, 可以通過自己建立模型有勾,給予分類疹启。
SettingArrowItem *oneItem = [SettingArrowItem itemWithIcon:@"test_icon" title:@"First" destVcClass:[FirstViewController class]];
SettingArrowItem *twoItem = [SettingArrowItem itemWithIcon:@"test_icon" title:@"Second" destVcClass:[SecondViewController class]];

SettingGroup *groupOne = [[SettingGroup alloc] init];
groupOne.items = [NSMutableArray arrayWithArray:@[oneItem,twoItem]];
[self.dataArray addObject:groupOne];
  • 點(diǎn)擊,相當(dāng)于之前已經(jīng)做好選擇了蔼卡,當(dāng)然這樣的應(yīng)用場景比較固定喊崖,也不利于擴(kuò)展。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    // 1.模型數(shù)據(jù)
    SettingGroup *group = self.dataArray[indexPath.section];
    SettingItem *item = group.items[indexPath.row];
    // 2雇逞、箭頭可以點(diǎn)擊
    if ([item isKindOfClass:[SettingArrowItem class]]) {
        SettingArrowItem *arrowItem = (SettingArrowItem *)item;
        // 如果沒有需要跳轉(zhuǎn)的控制器
        if (arrowItem.destVcClass == nil) return;
        UIViewController *vc = [[arrowItem.destVcClass alloc] init];
        vc.title = arrowItem.title;
        [self.navigationController pushViewController:vc animated:YES];
    }
}

這一種處理贷祈,相當(dāng)于是簡單的封裝數(shù)據(jù),讓點(diǎn)擊時(shí)更方便喝峦,當(dāng)然一些小部分的Cell 樣式也是可以任意改變的,然而還是認(rèn)為應(yīng)用場景有限呜达,只能針對于Account 頁面的點(diǎn)擊谣蠢,如微信那個人界面。

二查近、嘗試眉踱,解決多種樣式,多種點(diǎn)擊(樣式不同霜威,點(diǎn)擊不同)

這是我們組長為更好的用 UITableView 特意做的一個數(shù)據(jù)管理器谈喳,ZHTableViewGroup,雖說有些細(xì)節(jié)處理不是很認(rèn)同戈泼,特別是 Demo 中某兩處小細(xì)節(jié)婿禽,同時(shí) Demo 也沒有呈現(xiàn)chu赏僧,但整體來說思路是很棒的,使用也是很方便的扭倾。

  • 數(shù)據(jù)處理淀零,此處的點(diǎn)擊事件,已經(jīng)放出來啦膛壹,樣式也是隨時(shí)可以改變啦
ZHTableViewGroup *group = [[ZHTableViewGroup alloc]init];
ZHTableViewCell *cellOne = [[ZHTableViewCell alloc]initWithTableView:self.homeTableView range:NSMakeRange(0, 6) cellHeight:44 cellClass:[HomeCellStyleOne class] identifier:KHomeCellStyleOneIdentifier];
cellOne.configCellComplete = ^(UITableViewCell *cell, NSIndexPath *indexPath) {
    HomeCellStyleOne *cellOne = (HomeCellStyleOne *)cell;
    cellOne.textLabel.text = @"One Title";
    cellOne.detailTextLabel.text = @"One Detail";
};
cellOne.didSelectRowComplete = ^(UITableViewCell *cell, NSIndexPath *indexPath) {
    NSLog(@"cell->%@,indexPath->%@",cell,indexPath);
};
[group addTableViewCell:cellOne];

ZHTableViewCell *cellTwo = [[ZHTableViewCell alloc]initWithTableView:self.homeTableView range:NSMakeRange(6, 5) cellHeight:44 cellClass:[HomeCellStyleTwo class] identifier:KHomeCellStyleOneIdentifier];
cellTwo.configCellComplete = ^(UITableViewCell *cell, NSIndexPath *indexPath) {
    HomeCellStyleOne *cellTwo = (HomeCellStyleOne *)cell;
    cellTwo.textLabel.text = @"Two Title";
    cellTwo.detailTextLabel.text = @"Two Detail";
};
cellTwo.didSelectRowComplete = ^(UITableViewCell *cell, NSIndexPath *indexPath) {
    NSLog(@"cell->%@,indexPath->%@",cell,indexPath);
};

[group addTableViewCell:cellTwo];
[self.dataSource addTableV
  • 而代理驾中,一如既往是照舊,只是需要固定一些寫法模聋。
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return self.dataSource.sectionNumber;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    ZHTableViewGroup *group = [self.dataSource groupWithIndex:section];
    return group.rowNumber;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    ZHTableViewGroup *group = [self.dataSource groupWithIndex:indexPath.section];
    UITableViewCell *cell = [group cellWithIndexPath:indexPath];
    return cell;
}

#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    ZHTableViewGroup *group = [self.dataSource groupWithIndex:indexPath.section];
    [group didSelectRowAtIndexPath:indexPath];
}

  • 關(guān)鍵方法:
/*!
 *  @brief 初始化cell托管的對象
 *
 *  @param tableView  cell所注冊的tableview
 *  @param range      cell的范圍
 *  @param cellHeight cell的高度
 *  @param cellClass  注冊cell的class
 *  @param identifier 注冊cell的標(biāo)識符
 *
 *  @return ZHTableViewCell
 */
- (instancetype)initWithTableView:(UITableView *)tableView range:(NSRange)range cellHeight:(CGFloat)cellHeight cellClass:(Class)cellClass identifier:(NSString *)identifier;

此處肩民,有很多細(xì)節(jié)方面,我不是很贊同其處理链方,例如 range Cell 的范圍持痰,當(dāng)然此種方式已經(jīng)能滿足我們大部分的場景的(不是統(tǒng)一數(shù)據(jù)的類型那種)。

另外侄柔,類命名也不認(rèn)同共啃, ZHTableViewCell 是屬于一個 Manager 的,不應(yīng)該直接命名為 Cell 結(jié)尾暂题,容易讓人誤解移剪。

三、看 《RETableViewManager》

于是我先去看看 RETableViewManager 薪者,希望可以解決一些疑惑纵苛。這個輪子就是為了解決多種樣式多種點(diǎn)擊的列表。

直接看一下其 最基本用法:

- (void)viewDidLoad {
    [super viewDidLoad];
    // 總的 Manager
    self.manager = [[RETableViewManager alloc] initWithTableView:self.tableView];
    // Section 
    RETableViewSection *section = [RETableViewSection sectionWithHeaderTitle:@"Test"];
    [self.manager addSection:section];
    // Cell Item (基本的 Item)
    RETableViewItem *customItem = [RETableViewItem itemWithTitle:@"String cell" accessoryType:UITableViewCellAccessoryDisclosureIndicator selectionHandler:^(RETableViewItem *item) {
        NSLog(@"Test: %@", item);
    }];
    // Section Add Item
    [section addItem:customItem];
}

大致可以了解到 Cell ,Section 通通都由一個 RETableViewManager 來整體管理言津,而且 Cell 處的點(diǎn)擊和樣式都是單獨(dú)控制的攻人,低耦合高內(nèi)聚,這樣可以任意添加 Cell(此處的 Cell 都是基于其自定義的Cell)悬槽,此處我的想法是自己是否也可以這樣做呢怀吻?當(dāng)然 Cell 是任意的,并不要遵循某個BaseCell初婆。

四蓬坡、理解改善

其實(shí)ZHTableViewGroup 已經(jīng)可以說對其樣式和對其點(diǎn)擊已經(jīng)抽離出來了,但可以對 ZHTableViewGroup 進(jìn)行三點(diǎn)改善磅叛,當(dāng)然也是可商榷的屑咳。

  • 1、類命名更規(guī)范弊琴,將 ZHTableViewCell ==> ZHTableViewManager 相對來說更正確兆龙。
  • 2、將 Rang 抽離出來敲董,這樣更利于理解和更利于優(yōu)化紫皇。
    如果不寫慰安,就是直接按照順序,一步一步添加上去坝橡,默認(rèn)順序
    泻帮。
  • 3、group 分組计寇,實(shí)際還是可以蓋上成當(dāng)真的分組時(shí)锣杂,自動有空行空出來,實(shí)際上換句話說就是可以說此處的結(jié)構(gòu)還可以優(yōu)化番宁。

晉級: 將高度自適應(yīng)元莫,暫時(shí)沒進(jìn)行,但是可以嘗試蝶押,不過從另一個角度來說踱蠢,通常如果類似我想應(yīng)用的場景,一般高度都是固定的棋电,所以也沒必要茎截,否則這個場景頁面就不知道什么情況啦。

例如:下面是我將其 Rang 取消后一個 Cell 往一個 Cell 的結(jié)果

@implementation ZHTableViewCell {
    NSRange _tempRange;
    UITableView *_tableView;
}

static NSUInteger number = 0;

- (instancetype)initWithTableView:(UITableView *)tableView cellHeight:(CGFloat)cellHeight cellClass:(Class)cellClass identifier:(NSString *)identifier {
    if (self = [super init]) {
        NSParameterAssert(tableView);
        NSParameterAssert(identifier);
        _tableView = tableView;
        NSDictionary *cellClassDict = [tableView valueForKey:@"_cellClassDict"];
        __block BOOL isExitRegister = NO;
        [cellClassDict.allKeys enumerateObjectsUsingBlock:^(NSString *  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            if ([obj isEqualToString:identifier]) {
                isExitRegister = YES;
            }
        }];
        if (!isExitRegister) {
            [tableView registerClass:cellClass forCellReuseIdentifier:identifier];
        }
        _tempRange = NSMakeRange(number, 1);
        number++;
        // _range = range;
        _cellHeight = cellHeight;
        _identifier = identifier;
    }
    return self;
}

- (BOOL)cellIsExitRangeWithIndex:(NSUInteger)index {
   // return NSLocationInRange(index, _range);
    return NSLocationInRange(index, _tempRange);
}

- (UITableViewCell *)cellWithIndexPath:(NSIndexPath *)indexPath {
    return [_tableView dequeueReusableCellWithIdentifier:_identifier forIndexPath:indexPath];
}

@end

此處這樣改完后赶盔,又發(fā)現(xiàn)沒必要企锌,一步一步加上去雖說好用,但是脫離出來其實(shí)也沒必要于未,只是老覺的這樣一連串參數(shù)初始化 感覺怪怪的撕攒。

如后期繼續(xù)擴(kuò)展維護(hù),寫法和規(guī)范像 RETableViewManager 學(xué)習(xí)是必要的烘浦。

PS : 目前ZHTableViewGroup 上傳的 DEMO 還有問題抖坪,仔細(xì)看就知道了,哈哈闷叉。

五擦俐、知識點(diǎn)

  • _cellClassDict 作為 UITableView 的私有變量,保存 cellClass 和 cellIden 用的握侧。

  • NSLocationInRange

NS_INLINE BOOL NSLocationInRange(NSUInteger loc, NSRange range) {
    return (!(loc < range.location) && (loc - range.location) < range.length) ? YES : NO;
}

類似這樣的內(nèi)斂捌肴,有時(shí)效果還是很巧妙的

  • 當(dāng)然更多的是對 UITableView 的熟悉度更加深了。


    效果圖

類似一連串的 View 的布局藕咏,我們就還是可以采用 UITableView, 可以解決上述淘寶 home 首頁那樣的問題,讓每一排 View 當(dāng)做一個 Cell秽五, 實(shí)現(xiàn)起來還是很方便的孽查。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市坦喘,隨后出現(xiàn)的幾起案子盲再,更是在濱河造成了極大的恐慌西设,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件答朋,死亡現(xiàn)場離奇詭異贷揽,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)梦碗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進(jìn)店門禽绪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人洪规,你說我怎么就攤上這事印屁。” “怎么了斩例?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵雄人,是天一觀的道長。 經(jīng)常有香客問我念赶,道長础钠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任叉谜,我火速辦了婚禮旗吁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘正罢。我一直安慰自己阵漏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布翻具。 她就那樣靜靜地躺著履怯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪裆泳。 梳的紋絲不亂的頭發(fā)上叹洲,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天,我揣著相機(jī)與錄音工禾,去河邊找鬼运提。 笑死,一個胖子當(dāng)著我的面吹牛闻葵,可吹牛的內(nèi)容都是我干的民泵。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼槽畔,長吁一口氣:“原來是場噩夢啊……” “哼栈妆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤鳞尔,失蹤者是張志新(化名)和其女友劉穎嬉橙,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寥假,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡市框,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了糕韧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片枫振。...
    茶點(diǎn)故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖兔沃,靈堂內(nèi)的尸體忽然破棺而出蒋得,到底是詐尸還是另有隱情,我是刑警寧澤乒疏,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布额衙,位于F島的核電站,受9級特大地震影響怕吴,放射性物質(zhì)發(fā)生泄漏窍侧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一转绷、第九天 我趴在偏房一處隱蔽的房頂上張望伟件。 院中可真熱鬧,春花似錦议经、人聲如沸斧账。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽咧织。三九已至,卻和暖如春籍救,著一層夾襖步出監(jiān)牢的瞬間习绢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工蝙昙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留闪萄,地道東北人。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓奇颠,卻偏偏與公主長得像败去,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子烈拒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評論 2 354

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

  • 概述在iOS開發(fā)中UITableView可以說是使用最廣泛的控件为迈,我們平時(shí)使用的軟件中到處都可以看到它的影子三椿,類似...
    liudhkk閱讀 9,039評論 3 38
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件葫辐、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,098評論 4 62
  • 1.form表單有什么作用?有哪些常用的input 標(biāo)簽伴郁,分別有什么作用耿战? 表單的作用是搜集用戶的輸入,用戶提交表...
    CYC_dc68閱讀 397評論 0 0
  • 只是你不知道而已
    馭臨風(fēng)閱讀 194評論 0 1
  • 1.運(yùn)營課程給我?guī)碜畛醯挠∠蠛退伎?我在知道需要完成這么一次學(xué)習(xí)實(shí)踐焊傅,開始的我還是比較逃避的剂陡,通過三節(jié)課的課程學(xué)...
    時(shí)光聽得見閱讀 240評論 0 0