溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何使用UITableView

發(fā)布時(shí)間:2021-11-15 10:49:31 來源:億速云 閱讀:140 作者:iii 欄目:移動(dòng)開發(fā)

這篇文章主要講解了“如何使用UITableView”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“如何使用UITableView”吧!

痛點(diǎn)

在我們iOS開發(fā)中UITableView幾乎是所有App都會(huì)使用的一個(gè)UI控件,因?yàn)闃I(yè)務(wù)的需要,我們常常會(huì)注冊多種Cell,然后在

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

中就會(huì)很自然的寫出一堆類似這樣的代碼:

如何使用UITableView

事件處理的代碼大概是這樣的:

如何使用UITableView

這似乎沒有什么問題,代碼很干凈,邏輯也比較清晰。

但是你維護(hù)幾個(gè)版本之后,或者遇到了一個(gè)善變的產(chǎn)品經(jīng)理。

你會(huì)發(fā)現(xiàn),這樣的代碼維護(hù)起來真的很危險(xiǎn),稍微一不注意就出錯(cuò)了,這里用的type作為判斷條件可能相較與indexPath要好一點(diǎn)。

如果使用indexPath作為判斷條件,如果你的cell順序有變化,或者有改動(dòng),那么你可能至少需要維護(hù)以下幾個(gè)地方:

  1. 你的模型數(shù)組

  2. cell dequeue的判斷條件

  3. 事件處理的判斷條件

  4. 。。。。

維護(hù)的東西越多,意味著你出錯(cuò)的概率是越大的。

那有沒有什么好的方法處理這類代碼?

分析

其實(shí)我們仔細(xì)想想,無論一個(gè)多么復(fù)雜的UITableView,與之對應(yīng)的其實(shí)只要一個(gè)模型數(shù)組。

那么我們?nèi)绻S護(hù)好了模型數(shù)組,是不是就維護(hù)好了UITableView中所有的cell,這是顯而易見的。

如果我們的UITableView中有N種cell樣式,那么模型數(shù)組中肯定也會(huì)有N種模型。

也就是說每種cell與每種模型是一一配對的,常規(guī)的模型與cell綁定是如上述的思路。

上述的思路,顯然不是我們想要的,維護(hù)起來太不便,而且耦合性也比較大。

想一想展示一個(gè)UITableView的過程

  1. 發(fā)起網(wǎng)絡(luò)請求

  2. JSON to Model,構(gòu)造模型數(shù)組

  3. 數(shù)據(jù)填充

大致就是這三步吧。

其實(shí)在第二步構(gòu)造模型數(shù)組時(shí),我們是不是就可以確定好UI的樣式了?

如果這里想不明白,再看看我們上面的分析,一種cell樣式對應(yīng)著一種模型,那么我們知道了模型,是不是就知道了cell樣式

如果你還是不大清楚,那們就進(jìn)入實(shí)戰(zhàn)部分

實(shí)戰(zhàn)

如何使用UITableView

先看這樣一個(gè)簡單的頁面,你肯定會(huì)說:朋友,你TM在逗我們,這和UITableView有毛關(guān)系?

這個(gè)界面需要UITableView

沒錯(cuò),這個(gè)界面在UIViewController中直接構(gòu)建就可以了。

請?jiān)倏聪旅?/h5>

如何使用UITableView

如何使用UITableView

是不是感覺都很類似,但是又有很多不同的地方。

方案

  1. 一個(gè)一個(gè)VC的寫。

缺點(diǎn):

有很多重復(fù)代碼,而且后期的改動(dòng)需要維護(hù)的地方,做不到高內(nèi)聚。

  1. 抽象一個(gè)父類

    缺點(diǎn):

    雖然三個(gè)VC看似UI上有很多共同之處,但是其中的業(yè)務(wù)處理完全不同的

  2. 抽象一個(gè)UIHelper用于構(gòu)建UI

    缺點(diǎn):

    這種方案看似很好了,但是你看如果在一個(gè)界面中,如果添加一個(gè)或者減少一個(gè)控件,又得重新做約束了,這也顯然不是我們想要的。

下面看看通過UITableView構(gòu)建的UI

展示

如何使用UITableView

SignInVC 中的代碼:

如何使用UITableView

如何使用UITableView

PasswordSignVC 中的代碼:

如何使用UITableView

再看cell的dequeue代碼

如何使用UITableView

數(shù)據(jù)的綁定,全部分散到了每個(gè)cell中。

Row.h的代碼

#import <UIKit/UIKit.h>NS_ASSUME_NONNULL_BEGIN@protocol Updatable <NSObject>@optional- (void)updateViewData:(id)viewData;@end@interface Row : NSObject@property(nonatomic, copy, readonly) NSString *reuseIdentifier;@property(nonatomic, strong, readonly) Class cellClass;@property(nonatomic, strong, readonly) id model;- (instancetype)initWithClass:(Class)cls model:(id)model;- (instancetype)initWithClass:(Class)cls;- (void)updateCell:(UITableViewCell *)cell;@endNS_ASSUME_NONNULL_END

Row.m的代碼

@interface Row()@property(nonatomic, strong, readwrite) Class cellClass;@property(nonatomic, strong, readwrite) id model;@end@implementation Row- (instancetype)initWithClass:(Class)cls {
    if (self = [self initWithClass:cls model:@""]) {
    }
    return self;}- (instancetype)initWithClass:(Class)cls model:(id)model {
    if (self = [super init]) {
        self.cellClass = cls;
        self.model = model;
    }
    return self;}- (void)updateCell:(UITableViewCell *)cell {
    if ([cell respondsToSelector:@selector(updateViewData:)]) {
        [cell performSelector:@selector(updateViewData:) withObject:self.model];
    }}- (NSString *)reuseIdentifier {
    return [NSString stringWithFormat:@"%@", self.cellClass];}@end

整個(gè)Row的代碼不過100行,把所有的處理都內(nèi)聚在了一起,我們只要維護(hù)好模型數(shù)組就能很好的管理UITableView

UI是構(gòu)建完成了,但是我相信其中有兩個(gè)問題你肯定比較關(guān)心
  1. Cell 高度計(jì)算

  2. Cell上事件的回調(diào)

Cell 高度計(jì)算

在iOS8之后UITableView中推出了Self-sizing的功能,所以Cell的高度改變

        UIView *dummyView = [[UIView alloc] init];
        dummyView.translatesAutoresizingMaskIntoConstraints = NO;
        [self.contentView insertSubview:dummyView belowSubview:self.textField];
        [dummyView.topAnchor constraintEqualToAnchor:self.contentView.topAnchor].active = YES;
        [dummyView.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor].active = YES;
        NSLayoutConstraint *constraint = [dummyView.heightAnchor constraintEqualToConstant:60];
        constraint.priority = 999;
        constraint.active = YES;

如果你對這塊不熟悉,請 跳轉(zhuǎn)。如果你想對Auto Layout有一個(gè)提高建議看看 Auto Layout Guide, 如果你想知道systemLayoutSizeFittingSize的作用,請看  深入理解Auto Layout 第一彈

Cell上事件的回調(diào)

有人肯定會(huì)不屑這里,但是我想說:如果不用block、代理、觀察者。

怎么把cell上button的事件回調(diào)到VC中(button沒有暴露給外部)?

我們先看添加Action的方法

- (void)addTarget:(nullable id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;

這里需要這三個(gè)參數(shù):

  • target(action的相應(yīng)者)

  • action(點(diǎn)擊按鈕相應(yīng)的方法)

  • controlEvents(這個(gè)一般為UIControlEventTouchUpInside)

只要我們找到了target,把a(bǔ)ction寫到target里這個(gè)action綁定是不是就完成了。

target其實(shí)就是我們的VC,我們只要把VC傳遞給Cell即可,但是這樣是不是Cell又和VC耦合了啊。這個(gè)用block,delegate沒什么區(qū)別吧!

現(xiàn)在我們需要解決的問題就是找到Cell的VC,大功即可告成。

這是就需要一個(gè)重要的概念閃亮登場iOS 響應(yīng)鏈(Responder Chain)

這里就不展開了,但是你一定要去了解這個(gè)。

響應(yīng)鏈可以解決的問題:

  • 擴(kuò)大相應(yīng)區(qū)域

  • 超出父類視圖相應(yīng)依然可以傳遞

  • 垮圖層傳遞事件

找到UIViewUIViewController

- (UIViewController *)viewController {
    UIResponder *responder = self;
    while (![responder isKindOfClass:[UIViewController class]]) {
        responder = [responder nextResponder];
        if (nil == responder) {
            break;
        }
    }
    return (UIViewController *)responder;}

ButtonCell事件綁定代碼:

如何使用UITableView

這里我們還是要用一個(gè)協(xié)議的:

如何使用UITableView

注意

用這個(gè)協(xié)議主要是方便代碼的閱讀,而且在Swift中是必須使用協(xié)議的,因?yàn)榫幾g時(shí)找不到這個(gè)方法。

可以看到ButtonCell的代碼中并沒有這樣一段代碼

@property (nonatomic, weak) id<ButtonCellActionable> delegate;

或者

@property (nonatomic, strong) void (^buttonAction)(void);

這樣我們的ButtonCell不會(huì)和VC耦合,修改起來真的很方便

感謝各位的閱讀,以上就是“如何使用UITableView”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對如何使用UITableView這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI