一.commentView模塊搭建 commentView樣式分為兩種 1.xib搭建界面 1.1 因為評論的樣式大體上一樣,我們可以用同一個xib來處理 1.2 最熱評論 用一個label來搭建 1.3 下麵的內容不一樣 1.3.1 文本樣式的評論,下麵也用一個label搭建就可以了 label約 ...
一.commentView模塊搭建 commentView樣式分為兩種 1.xib搭建界面 1.1 因為評論的樣式大體上一樣,我們可以用同一個xib來處理 1.2 最熱評論 用一個label來搭建 1.3 下麵的內容不一樣 1.3.1 文本樣式的評論,下麵也用一個label搭建就可以了 label約束設置為左右和上面固定間距,這樣,高度會隨著內容縮放,前提是設置label為0行 1.3.2 聲音樣式評論 聲音樣式的評論.高度是固定的 先添加一個view在文本評論的位置(根據數據再決定到時候哪種樣式的評論顯示,上面的部分是一樣的) 再往view裡面添加一個label 和 button 就行了 註意:button的圖片和文字有間距 只需要設置內部子控制項的內邊距就行了 如果label下麵對view有約束,button下麵就不要對view設置約束了 會有衝突, 總之,設置其中一個,另一個就不要設置了 2.請求數據 2.1 在設置模型屬性的時候,我們要對數據進行處理
2.2 從上圖中可以看到,我們需要拿到username 首先要拿到top_cmt這個數組,然後再拿到 user字典 2.3 我們習慣都是面向模型開發,所以我們拿到 top_cmt 數組的第一個元素(字典) 轉為模型 2.4 然後取出字典中的user字典,在轉為另一個模型 2.5 那麼我們就需要先自定義兩個模型 2.6 我們最好在最外層模型中定義一個模型屬性,來保存內層的一個模型(item0 也是就是評論模型) 為什麼? 在取內層模型屬性的時候,會因為層級太深,需要寫很長一段代碼 進行這樣的優化後,取內層模型屬性的時候,就方便很多 2.7 怎麼把模型中的數組屬性裡面的字典轉換為 模型中的一個屬性 重寫數組元素的set方法 只要拿到數組中的字典元素,給模型中的這個屬性賦值 為了嚴謹,要判斷數組是否為空
1 // 給模型的top_cmt屬性賦值調用 2 - (void)setTop_cmt:(NSArray *)top_cmt 3 { 4 _top_cmt = top_cmt; 5 if (top_cmt.count) { 6 _commentItem = top_cmt.firstObject; 7 } 8 } 9
3.怎麼在外層模型裡面,把模型中的數組屬性中的字典(或字典屬性)轉成模型? 有兩種方法來轉 3.1第一種方法 ,自己手動利用MJ框架來轉 3.2第二種方法,讓MJ框架自動幫我們轉,(前提是MJ框架知道模型中屬性要轉成哪種類型的模型) 3.3 MJ框架怎麼自動幫我們轉內層模型? MJExtension:如果模型中有模型,MJExtension會自動幫你轉換好 @property (nonatomic, strong) XTUserItem *user; 因為我們在定義這個字典的時候,就告訴MJ框架,要把字典轉為哪種類型的模型 MJExtension:如果模型中有數組,數組中又是字典,MJExtension不會自動幫你轉 MJExtension可以把數組中字典轉模型 ,但是需要告訴他要把數組中的字典轉為哪種類型的模型 3.4 怎麼告訴MJ把數組中的字典轉為哪種類型的模型
1 // key:哪個數組需要轉換 2 + (NSDictionary *)mj_objectClassInArray 3 { 4 return @{@"top_cmt":@"XTCommentItem"}; 5 } 6
3.5 MJExtension底層實現 3.5.1 MJ底層是利用KVC對模型進行賦值的 遍歷模型中的key, 然後去字典中查找對應的value對key賦值 3.5.2 利用kvc賦值,模型中可以沒有字典中的某些key值, 但模型中的key 在字典中一定要有對應的value,否則會報錯 MJ框架不存在這個問題, kvc底層實現: http://www.jianshu.com/p/45cbd324ea65 KVC是通過[item setValuesForKeysWithDictionary:dict]這個方法,將字典轉為模型 setValuesForKeysWithDictionary:底層實現 便利字典當中的所有Key Value值.給對應的key,value賦值 [dict enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { 給對應的key,value賦值 setValuesForKeysWithDictionary:會調用setValue:forKeyPath: [item setValue:obj forKeyPath:key]; }]; setValue:forKeyPath:的底層實現: setValue: forKeyPath: 1.根據key值與當前的屬性進行對比,先去看有沒有與key值相同的set方法.如果有,就調用set方法. 2.如果沒有,再去對比,有沒有跟key值相同的成員屬性,如果有,就直接進行賦值. 3.如果沒有,再去對比,有沒有跟key值相同的而且帶有下劃線的成員屬性,如果有,就直接進行賦值. 4.如果還沒有,會調用setValue:(id)value forUndefinedKey: 5.如果沒有實現,直接報錯. 3.5.3 kvc要求,在模型中定義的key值得數據類型 一定要跟字典中key對應的value的值的數據類型相同,否則會報錯 3.5.4 MJ框架,能夠把一些key值的數據類型自動轉換為和字典中key對應的value的數據類型(前提是,這個兩種數據類型能相互轉換) 4.在視圖模型中計算cell子控制項的frame和高度
1 if (item.commentItem) { // 先判斷有沒有最熱評論,有評論才需要計算 2 CGFloat commentH = 42; 聲音評論,高度是確定的 3 註意點:以後只要判斷字元串有沒有內容,用長度 4 if (item.commentItem.content.length) { // 有內容,就是文本評論 5 根據文字的高度來計算評論的高度 6 NSString *totalStr = [NSString stringWithFormat:@"%@:%@",item.commentItem.user.username,item.commentItem.content]; 7 textH = [totalStr sizeWithFont:[UIFont systemFontOfSize:17] constrainedToSize:CGSizeMake(textW, MAXFLOAT)].height; 8 commentH = 21 + textH; 9 } 10 CGFloat commentW = textW; 11 CGFloat commentX = margin; 12 CGFloat commentY = _cellH; 13 _commentViewFrame = CGRectMake(commentX, commentY, commentW, commentH); 14 _cellH = CGRectGetMaxY(_commentViewFrame) + margin; 15 }5.展示數據 可以根據top_cmt數組的元素個數來判斷commentView是否顯示 或者根據這個數組中的元素轉換的模型是否存在判斷 二.bottomView模塊搭建 此界面搭建相對來說比較簡單,就不做具體介紹了 1.xib搭建界面 2.請求數據 2.1 查看介面文檔,使用afn發送網路請求 2.2網路請求成功時,把數據轉換成模型 2.3在模型中定義屬性(先自定義模型) 查看界面需要使用哪些數據,就找到定義數據的屬性定義到模型中 2.3自定義視圖模型,視圖模型包含模型(就是在視圖模型中定義一個模型的屬性) 2.4遍歷模型,全部轉換為視圖模型 創建視圖模型對象 用視圖模型的模型屬性來接收模型 把視圖模型保存到數組中 3.在視圖模型中計算cell子控制項的frame和高度 高度給一個固定值就行了,cell的高度就是Y軸方向最後一個控制項的最大Y值 4.展示數據 4.1展示數據的方法都一樣,這裡主要是對數據進行一些處理 4.2當評論或贊的數字超過一萬的時候要進行處理 4.2.1 超過一萬,讓總數除以一萬,得到的數字保留一位小數,顯示xx.x萬 4.2.2 如果總數為0的話,顯示在界面上,效果很差,我們要進行一些處理 如果數據為0, 我們就在界面顯示占位文字
1 處理數據原碼 2 - (void)setItem:(XTThemeItem *)item 3 { 4 [super setItem:item]; 5 6 [self setButton:_dingView count:item.ding title:@"贊"]; 7 [self setButton:_caiView count:item.cai title:@"踩"]; 8 [self setButton:_shareView count:item.repost title:@"轉發"]; 9 [self setButton:_commentView count:item.comment title:@"評論"]; 10 } 11 12 - (void)setButton:(UIButton *)button count:(NSInteger)count title:(NSString *)title 13 { 14 如何抽取一個方法:先把要抽取成方法的源代碼拷貝過來,缺什麼補什麼就行了,需要外界決定的東西,寫成參數,讓外界傳遞進來 15 CGFloat valueF = 0; 16 NSString *str = title; 17 if (count > 10000.0) { 18 valueF = count / 10000.0; 19 str = [NSString stringWithFormat:@"%.1f萬",valueF]; 20 str = [str stringByReplacingOccurrencesOfString:@".0" withString:@""]; 21 } else if (count > 0) { 22 str = [NSString stringWithFormat:@"%ld",count]; 23 } 24 [button setTitle:str forState:UIControlStateNormal]; 25 } 26
三.處理cell的外觀細節 1.cell的選中樣式很難看,我們怎麼取消? 1.1 設置cell的一個屬性就可以了
self.selectionStyle = UITableViewCellSelectionStyleNone;1.2 在哪裡寫代碼? 在初始化cell方法裡面寫
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
2.我們想把分割線設置的寬一點,怎麼設置? 首先,我們要先取消系統的分割線
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;2.1自定義分割線 給cell的底部加一個uiview設置高度和顏色能達到分割線的效果 2.2 設置cell的frame,讓cell的高度減少一個值,減少的部分就能看到背景色,只需要設置背景色就可以達到設置分割線的目的 註意:在這裡減少的值,一定要在設置cell的高度的時候加上去,否則cell可能被壓縮
1 設置frame源代碼 2 - (void)setFrame:(CGRect)frame 3 { 4 frame.origin.y += 10; 5 frame.size.height -= 10; 6 註意:一定要調用super方法 7 [super setFrame:frame]; 8 }2.3 給cell設置背景圖片 通過 backgroundView屬性給cell設置背景圖片,只需要給cell的 backgroundView設置UIImageView就可以了 設置完發現,背景圖片邊緣有些難看,很有可能是圖片被拉伸了,我們要對圖片進行處理 設置圖片的可拉伸區域,然後再設置cell的背景圖片
1 設置cell背景圖片原碼 2 UIImage *image = [UIImage imageNamed:@"mainCellBackground"]; 3 處理圖片:設置可拉伸區域 4 image = [image stretchableImageWithLeftCapWidth:image.size.width * 0.5 topCapHeight:image.size.height * 0.5]; 5 6 self.backgroundView = [[UIImageView alloc] initWithImage:image];