這篇文章主要講解了“如何使用UITableView”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“如何使用UITableView”吧!
在我們iOS開發中UITableView
幾乎是所有App都會使用的一個UI控件,因為業務的需要,我們常常會注冊多種Cell,然后在
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
中就會很自然的寫出一堆類似這樣的代碼:
事件處理的代碼大概是這樣的:
這似乎沒有什么問題,代碼很干凈,邏輯也比較清晰。
但是你維護幾個版本之后,或者遇到了一個善變的產品經理。
你會發現,這樣的代碼維護起來真的很危險,稍微一不注意就出錯了,這里用的type
作為判斷條件可能相較與indexPath
要好一點。
如果使用indexPath
作為判斷條件,如果你的cell順序有變化,或者有改動,那么你可能至少需要維護以下幾個地方:
你的模型數組
cell dequeue的判斷條件
事件處理的判斷條件
。。。。
維護的東西越多,意味著你出錯的概率是越大的。
那有沒有什么好的方法處理這類代碼?
其實我們仔細想想,無論一個多么復雜的UITableView
,與之對應的其實只要一個模型數組。
那么我們如果維護好了模型數組,是不是就維護好了UITableView
中所有的cell,這是顯而易見的。
如果我們的UITableView
中有N種cell樣式,那么模型數組中肯定也會有N種模型。
也就是說每種cell與每種模型是一一配對的,常規的模型與cell綁定是如上述的思路。
上述的思路,顯然不是我們想要的,維護起來太不便,而且耦合性也比較大。
想一想展示一個UITableView
的過程
發起網絡請求
JSON to Model,構造模型數組
數據填充
大致就是這三步吧。
其實在第二步構造模型數組時,我們是不是就可以確定好UI的樣式了?
如果這里想不明白,再看看我們上面的分析,一種cell樣式對應著一種模型,那么我們知道了模型,是不是就知道了cell樣式
如果你還是不大清楚,那們就進入實戰部分
先看這樣一個簡單的頁面,你肯定會說:朋友,你TM在逗我們,這和UITableView
有毛關系?
這個界面需要UITableView
?
沒錯,這個界面在UIViewController
中直接構建就可以了。
是不是感覺都很類似,但是又有很多不同的地方。
一個一個VC的寫。
缺點:
有很多重復代碼,而且后期的改動需要維護的地方,做不到高內聚。
抽象一個父類
缺點:
雖然三個VC看似UI上有很多共同之處,但是其中的業務處理完全不同的
抽象一個UIHelper用于構建UI
缺點:
這種方案看似很好了,但是你看如果在一個界面中,如果添加一個或者減少一個控件,又得重新做約束了,這也顯然不是我們想要的。
下面看看通過UITableView
構建的UI
SignInVC 中的代碼:
PasswordSignVC 中的代碼:
再看cell的dequeue代碼
數據的綁定,全部分散到了每個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
整個Row的代碼不過100行,把所有的處理都內聚在了一起,我們只要維護好模型數組就能很好的管理UITableView
Cell 高度計算
Cell上事件的回調
在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;
如果你對這塊不熟悉,請 跳轉。如果你想對Auto Layout有一個提高建議看看 Auto Layout Guide, 如果你想知道
systemLayoutSizeFittingSize
的作用,請看 深入理解Auto Layout 第一彈
有人肯定會不屑這里,但是我想說:如果不用block、代理、觀察者。
怎么把cell上button的事件回調到VC中(button沒有暴露給外部)?
我們先看添加Action的方法
- (void)addTarget:(nullable id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;
這里需要這三個參數:
target(action的相應者)
action(點擊按鈕相應的方法)
controlEvents(這個一般為UIControlEventTouchUpInside)
只要我們找到了target,把action寫到target里這個action綁定是不是就完成了。
target其實就是我們的VC,我們只要把VC傳遞給Cell即可,但是這樣是不是Cell又和VC耦合了啊。這個用block,delegate沒什么區別吧!
現在我們需要解決的問題就是找到Cell的VC,大功即可告成。
這是就需要一個重要的概念閃亮登場iOS 響應鏈(Responder Chain)
這里就不展開了,但是你一定要去了解這個。
響應鏈可以解決的問題:
擴大相應區域
超出父類視圖相應依然可以傳遞
垮圖層傳遞事件
找到UIView
的UIViewController
- (UIViewController *)viewController { UIResponder *responder = self; while (![responder isKindOfClass:[UIViewController class]]) { responder = [responder nextResponder]; if (nil == responder) { break; } } return (UIViewController *)responder;}
ButtonCell事件綁定代碼:
這里我們還是要用一個協議的:
用這個協議主要是方便代碼的閱讀,而且在Swift中是必須使用協議的,因為編譯時找不到這個方法。
可以看到ButtonCell的代碼中并沒有這樣一段代碼
@property (nonatomic, weak) id<ButtonCellActionable> delegate;
或者
@property (nonatomic, strong) void (^buttonAction)(void);
這樣我們的ButtonCell不會和VC耦合,修改起來真的很方便
感謝各位的閱讀,以上就是“如何使用UITableView”的內容了,經過本文的學習后,相信大家對如何使用UITableView這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創新互聯,小編將為大家推送更多相關知識點的文章,歡迎關注!
分享標題:如何使用UITableView-創新互聯
本文鏈接:http://vcdvsql.cn/article20/jepjo.html
成都網站建設公司_創新互聯,為您提供網站設計、響應式網站、品牌網站制作、標簽優化、電子商務、域名注冊
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯