我寫的源文件整個工程會再第二季中發上來~,存在百度網盤, 感興趣的童鞋, 可以關注我的博客更新,到時自己去下載~。喵~~~
1.將假數據messages.plist和icon圖片文件導入工程中。
#import <UIKit/UIKit.h>typedef enum { MessageWhoIsMe, MessageWHoIsAnother}MessageWho;@interface Message : NSObject@PRoperty (nonatomic, strong) NSString * text;@property (nonatomic, strong) NSString * time;@property (nonatomic, assign) MessageWho type;@property (nonatomic, assign) CGFloat height;+ (instancetype)messageWithDict:(NSDictionary *)dict;@end
喵喵~~~~~,好鳥.所有準備工作都做好了。接下去要開始編碼了, 啥?這就好了。是滴,接下去可要認真聽我分析鳥, 交你為什么要這么寫代碼。大神請繞道~。
第一步:因為我們使用的是假數據,也就是plist文件中的數據進行模擬。所以我們省略掉從網絡中獲取數據這一步。我們只需要把plist的數據先加載進來就好了。那么怎么加載數據呢,為了提高程序的效率,我們使用懶加載了加載數據, 也就是在要用到數據的地方, 數據才會自動加載并緩存起來。喵~~~,好像很神奇的樣子,嚇得我都做地上了。
@interface ViewController () <UITableViewDataSource, UITableViewDelegate>@property (weak, nonatomic) IBOutlet UITableView *tableView;/** * 存放所有對話的緩存數組 */@property (nonatomic, strong) NSArray * messages;@end
// 懶加載- (NSArray *)messages { if (_messages == nil) { NSString * path = [[NSBundle mainBundle] pathForResource:@"messages" ofType:@"plist"]; NSArray * dictArray = [NSArray arrayWithContentsOfFile: path]; NSMutableArray * messages = [NSMutableArray array]; for (NSDictionary * dict in dictArray) { Message * message = [Message messageWithDict: dict]; [messages addObject: message]; } _messages = messages; } return _messages;}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.messages.count;}
estimatedRowHeight
,我們只需統一的設置預估屬性的大小,或者是為每一行(也就是每個cell)設置預估計的cell高度, 那么就會先調用cellForRowAtPath進行cell對象的創建,并且使用預估計的高度創建初始化的cell,但是當要顯示到界面上時候,還會再調用heightForRowAtPath.為了方便, 我直接使用的是提供統一的預估算高度,然后實現這兩個方法,如下代碼。- (void)viewDidLoad { [super viewDidLoad]; self.tableView.estimatedRowHeight = 120; // Do any additional setup after loading the view, typically from a nib.}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString * ID = @"messageCell"; MessageCellTableViewCell * cell = [self.tableView dequeueReusableCellWithIdentifier:ID]; cell.message = self.messages[indexPath.row]; return cell;}- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return ((Message *)self.messages[indexPath.row]).height;}
cell.message = self.messages[indexPath.row];
。我想實現的是將數據模型直接傳遞給cell對象,應為我們沒必要將view層的東西暴露在controller層中,view層的東西都是和數據相關的, 這樣我們就能做到邏輯和數據的分離,好處是,打個比方,如果你項目中有10幾個controller也需要用到這個cell,那么他們就要重復的在controller中寫10多行的操作數據的操作,這是不明智的,也是不好的封裝,所以我們應該將這些代碼封裝進cell對象所屬于的類中,cell的事情,cell自己去處理.這樣封裝,controller就不必關心cell如何處理這些數據,只需要將數據交給cell處理就行。于是我們現在就可以來到UIMessageCell類中,給其加上Message類的message屬性,并且重寫setter,再setter中,我們需要做3件事情,第一件事情保留message對,第二件事情是進行控件上數據的展示,第三件事是在數據填充完后計算cell的高度,并將其更行到數據模型上。(計算高度的時候我們需要兩次使用layoutIfNeeded來強制布局,具體原因看下面注釋)@implementation MessageCellTableViewCell// 取得對應頭像的圖片名- (NSString *)getPicture:(MessageWho)who { return who == MessageWhoIsMe? @"me" : @"other";}- (void)setMessage:(Message *)message { // 1.給控件裝數據 _message = message; _icon.image = [UIImage imageNamed:[self getPicture: message.type]]; [_text setTitle:message.text forState:UIControlStateNormal]; _timeLabel.text = message.time; // 2.裝完數據強制布局, 使得設置按鈕高度的值準確, 并且更新約束 [_text layoutIfNeeded]; // 要先強制布局, 這時候更新約束才準確 // 更新約束, 使得按鈕的高度此時等于文本的高度。 /* When creating a custom button—that is a button with the type UIButtonTypeCustom—the frame of the button is set to (0, 0, 0, 0) initially. Before adding the button to your interface, you should update the frame to a more appropriate value. 當按鈕是custom樣式的時候, 其frmae的值都是零。 按鈕里面的label默認是不自動換行的。 */ [_text updateConstraints:^(MASConstraintMaker *make) { CGFloat textH = CGRectGetHeight(_text.titleLabel.frame); make.height.equalTo(textH); }]; // 3.再次強制布局, 使得約束生效, 這樣獲取到的按鈕高度才準確 [_text layoutIfNeeded]; CGFloat textH = CGRectGetMaxY(_text.frame); CGFloat iconH = CGRectGetMaxY(_icon.frame); CGFloat cellH = MAX(textH, iconH) + 10; // 4.更新cell的高度到模型中 _message.height = cellH;}- (void)awakeFromNib { // 設置自動換行 _text.titleLabel.numberOfLines = 0;}- (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; // Configure the view for the selected state}
新聞熱點
疑難解答