2014年過的那麼快,過年又那麼塊,2015年又是飛快地節奏,真尼瑪感受上帝是否是無聊使用了變速外掛開啓了加速模式~到如今博主都沒法接受已 經上班的事實……在地鐵臉被擠在玻璃上的時候只能用眼神寫滿傻X射這個世界一臉!!原諒博主那麼雞糞~由於哥最近生病了,不嗨心~,我想來去想不明白,博 主每週健身4天,胸肌壓女朋友、拳頭比沙煲、吃喝健又康、體硬似野馬,怎麼會生病呢?我苦思多日,終於有一天早上起牀看了鏡子半個小時後我才頓悟,我靠~原 來長得帥真的是錯!上帝在嫉妒我才讓我生病的~哈哈哈 咳咳~這是一個嚴肅的技術博客~是絕對拒絕惡俗低下的內容的,大丈夫應該心繫天下才對,最近柴靜和霧霾真的觸動了咱們每一個人的心;某極端組織像嗨大了一 樣,真的是屠龍寶刀在手,裝備任爆的節奏;近下的港島撐完雨傘又要趕人了……我真的是很是痛心疾首,維護世界和平一直是鄙人的願望,如今的世界這麼混亂, 本人真的很慚愧,都怪我咯~~沒有由於什麼,因此今天博主要教你們怎麼寫一個本身用着安逸,修改巴適,他人用起來又無比舒服的iOS庫!!git
本人不才,接觸代碼的世界時間真心不是好久,對於系統底層優化、框架級別設計、設計模式的效率優劣等方面的學習和研究比不深入,因此若是你是大神, 你狠溜的話,我仍是建議您路過呵呵一下而後就關了這個網頁吧,雕蟲小技沒法入爾法眼啊~我不是怕被噴很菜(反正都被老師噴了二十年了……^_^)而是我對 大神都是有敬畏之心的,不能說讓你看你就看,你能夠試一下是吧,你也不喜歡看完後是Duang 那麼多特效 特技……咳咳 反正這篇文章真的很菜~~~適合比我菜的菜鳥,慎讀。github
不過嘛咱們要寫一個庫,可以讓別人用,用起來要很舒服的,那確定得要設計得當,確定要熟悉平臺,設計模式很是溜才行,這個沒錯~可是平臺、架構、設計這個東西這麼複雜,我解釋你們也不懂,那我就不解釋了(你強迫症發做死都要懂可自行找一個大學,裏面有老師~)設計模式
我發誓不扯BB了 咱們一塊兒來寫一個能被舒服舒服又舒服地調用的iOS庫,最近衛生紙漲價了,好煩,其實也是有緣由的,由於畢竟生產費用什麼的也都…我頭上的磚頭誰扔的!!??信不信我不打死你丫的……數組
假設咱們要開發一個像微信朋友圈或者微博這玩意兒的東西,而且要有能隱藏和展開正文、正文中可以識別富文本(網址、電話、@姓名……)、還要有圖片縮略圖並且點擊查看、可以有回覆、回覆文中也要支持富文本……這些功能。像這樣微信
圖1架構
所謂君子生非異也 善假於物也。上面的功能這麼多這麼複雜本身寫,你肯定你不是吃飽了撐着?經理也說要敏捷開發,因此二話不說閃現到code4app,code.cocoachina祭出最強殺器——搜索引擎,找到了這個庫WFCoretext 發現它完美符合咱們的需求呀,棒棒噠app
首先咱們感謝WFCoretext 的做者的開源貢獻,請收下個人膝蓋,咱們立刻來用一用~框架
圖2less
槽點很少異步
咱們來分析分析它怎麼搞得把
工程結構 圖3
嗯額 仍是比較簡單的 View文件夾裏面的是控件啦
圖4
具體實現 你們能夠本身看啦,這位哥哥代碼風格仍是比較規範的,看起來不費勁
Manager文件夾中是一些富文本匹配規則,其中YMTextData很重要 下面說
咱們直接來看看怎麼使用的把
點開WXViewController
導包而且聲明變量,變量在實現接下來的實現中會進行初始化
#import "WXViewController.h" #import "YMTableViewCell.h" #import "ContantHead.h" #import "YMShowImageView.h" #import "YMTextData.h" #import "YMReplyInputView.h" #define dataCount 10 #define kLocationToBottom 20 #define kAdmin @"小虎-tiger" @interface WXViewController ()<UITableViewDataSource,UITableViewDelegate,cellDelegate,InputDelegate> { NSMutableArray *_imageDataSource; NSMutableArray *_contentDataSource;//模擬接口給的數據 NSMutableArray *_tableDataSource;//tableview數據源 NSMutableArray *_shuoshuoDatasSource;//說說數據源 UITableView *mainTable; UIButton *replyBtn; YMReplyInputView *replyView ; } @end
這三個方法分別構建初始化了一個tableview,初始化並賦值圖片數據,初始化並賦值其餘數據
- (void) initTableview; - (void)configImageData; - (void)loadTextData;
在loadTextData中
會將數據包裝成YMTextData的數組,這樣一個tableCell裏面的數據就使用一個YMTextData的數據
而後在- (void)calculateHeight:(NSMutableArray *)dataArray
中會計算出數據所佔用view的高度 這裏面也就實現了 咱們需求裏面能夠擴展能夠收縮的功能
計算完高度而後就從新加載tableview了 而後tableview的各類delegate方法 各類datasource方法就呼呼的運行了
其中 如下方法中又再次使用了咱們在- (void)calculateHeight:(NSMutableArray *)dataArray
方法中計算出來的高度來設置tablecell的高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { YMTextData *ym = [_tableDataSource objectAtIndex:indexPath.row]; BOOL unfold = ym.foldOrNot; return TableHeader + kLocationToBottom + ym.replyHeight + ym.showImageHeight + kDistance + (ym.islessLimit?0:30) + (unfold?ym.shuoshuoHeight:ym.unFoldShuoHeight) + kReplyBtnDistance; }
如下這個方法又把YMTextData 賦值給了YMTableViewCell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *CellIdentifier = @"ILTableViewCell"; YMTableViewCell *cell = (YMTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[YMTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } cell.stamp = indexPath.row; cell.replyBtn.tag = indexPath.row; cell.replyBtn.appendIndexPath = indexPath; [cell.replyBtn addTarget:self action:@selector(replyAction:) forControlEvents:UIControlEventTouchUpInside]; cell.delegate = self; [cell setYMViewWith:[_tableDataSource objectAtIndex:indexPath.row]]; return cell; }
阿拉巴拉…… 呼呼
我就想問你一句 累不累?
如今我分析了一遍這個庫,你知道該怎麼用了麼,不要懷疑本身的智商,我也要再看一遍才知道怎麼用。
固然咱們不能懷疑做者對於開源技術作出的貢獻!咱們也不能懷疑做者的開發技術,畢竟這個庫的bug仍是比較少的,做者是偉大崇高的!減小了世界的碳 排量方便了你我他,爲不少代碼工做者提供了方便,讓他們能夠不加班,早早的回家陪老婆陪基友陪孩子陪寵物……因此我要再次感謝做者
可是做爲一個有完美強迫症的博主,問本身一句 爲何這個庫那麼難用?由於它難用
怎麼纔算是好用?系統自帶的組件,使用和學習起來那麼容易?這應該算是好用吧。
因此接下來,咱們要開刀WXViewController 讓他DUANG的一下,變得使用起來 舒服舒服又舒服!!
咱們不妨WXViewController的實現細節都封裝起來!它是一個tableview、它怎麼計算高度,它的回覆按鈕怎麼生成……巴拉巴拉我都不想管!!個人願望是,我只要扔進去數據,就自動生成一個朋友圈出來!!!!
有了願望,急着召喚神龍也沒用!規則是要集齊龍珠呀!!!好咱們先幹起來!整容WXViewController!!!
咱們要開發一個東西就叫作 「朋友圈模板」吧 在「朋友圈模板.h」中要有一個「朋友圈模板Delegate」 而後裏面要有一個方法-(返回的數據*)每行朋友圈的數據:index;
咱們使用的時候就這樣:
//真朋友圈.h @interface 真朋友圈 : 朋友圈模板<朋友圈模板Delegate> @end 真朋友圈.m @implementation 真朋友圈 - (void)viewDidLoad { self.delegate = self; } -(返回的數據*)每行朋友圈的數據:index{ return [朋友圈數據數組 objectAtIndex:index]; } @end
這樣就行了!你就不再用關心朋友圈怎麼實現了 你只要關係你的數據部分!!就問你Nice不Nice???
因此這裏只要你開發好了「朋友圈模板.m」那麼之後「朋友圈模板.h」和「朋友圈模板.m」就是你寫好的能被人舒服舒服又舒服調用的庫了!酷不酷??
博主就手把手教你怎麼寫這個「朋友圈模板.m」吧 嘻嘻嘻 手把手哦 呵呵呵 手 把 手喲 博主是頗有愛的哦~~~~
咱們要開發一個DDRichTextViewController
來代替WXViewController
<——這個太難用了
咱們先來寫寫DDRichTextViewController.h
嘛
//學學系統組件 咱們也來弄一個delegate和datasource~ 其實都是delegate爲了更好地區分功能,datasource主要用來設置數據有關 @protocol DDRichTextViewDelegate @required -(NSString*)senderName;//必需要實現!否則評論別人的時候沒名字 最恨匿名渣渣,本身叫的名字都不敢直接說!!「有誰知道我買充氣娃娃都匿名呢 呵呵,啊?爲何我內心想的會變成文字顯示出來!!!納尼!!」 @optional -(BOOL)hideReplyButtonForIndex:(NSInteger)index;//是否隱藏回覆按鈕,有時候咱們不讓人回覆 就把回覆按鈕隱藏起來了 -(void)didPromulgatorPressForIndex:(NSInteger)index name:(NSString*)name;//發佈者的頭像或者名字被點擊 -(void)didRichTextPressedFromText:(NSString*)text index:(NSInteger)index;//正文的富文本被點擊的回調 -(void)didRichTextPressedFromText:(NSString*)text index:(NSInteger)index replyIndex:(NSInteger)replyIndex;//評論的富文本被點擊的回調 -(void)replyForIndex:(NSInteger)index replyText:(NSString*)text;//回覆文字的內容的回調 @end @protocol DDRichTextViewDataSource @required -(YMTextData*)dataForRowAtIndex:(NSInteger)index;//這個就是每行須要的數據了! -(NSInteger)numberOfRowsInDDRichText;//須要返回多少行 @end @interface DDRichTextViewController : UIViewController<UITableViewDataSource,UITableViewDelegate,cellDelegate,InputDelegate> @property (weak, nonatomic) id delegate; @property (weak, nonatomic) id dataSource; @end
而後就是DDRichTextViewController.m
了
基本上就是對WXViewController.m
的封裝了! 讓其內部實現的細節都對使用者透明化
好比在DDRichTextViewController
中實現了uitableView的datasource和delegate
在這個方法中 tableview須要顯示的行數就由繼承DDRichTextViewController
的子類的datasource中的
-(NSInteger)numberOfRowsInDDRichText;
這個方法返回的數據做爲參數!
好比這樣:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return [[self dataSource] numberOfRowsInDDRichText]; }
因此當咱們使用咱們本身寫的庫的時候根本不在意這個方法
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
由於咱們封裝到了
-(NSInteger)numberOfRowsInDDRichText;
相似其餘實現以及方法都進行了封裝
這當中處理@required很簡單,用戶必須已經實現了 因此直接調用就好 。 可是 @optional的方法用戶不必定會去實現,因此當中最重要的就是要去判斷這個方法存不存在:方法以下
respondsToSelector:NSSelectorFromString(@「方法名:」) //這個凡是繼承NSObject的類都擁有這個方法 這個是基礎了,是運行時判斷方法存不存在的
詳細以下
if ([self.delegate respondsToSelector:NSSelectorFromString(@"hideReplyButtonForIndex:")]) { //判斷hideReplyButtonForIndex方法存不存在 存在纔會執行以下的代碼 if ([[self delegate] hideReplyButtonForIndex:indexPath.section]) { cell.hideReply = YES; } }
下面是詳細的代碼
(原本想貼詳細代碼的,博主一思忖!最好下載個人Demo進行研究 這樣能夠在方法之間跳轉 更能看得懂!!地址在文後!並且大家在博主的Demo項目中star一下 我就愛死你Y的了)
最後咱們來看看怎麼使用寫好的DDRichTextViewController
咱們新建一個TestViewController
//TestViewController.h #import "DDRichTextViewController.h" @interface TestViewController : DDRichTextViewController<DDRichTextViewDataSource,DDRichTextViewDelegate> @end
// // TestViewController.m // #import "TestViewController.h" @implementation TestViewController NSMutableArray * ymDataArray; - (void)viewDidLoad { [super viewDidLoad]; NSMutableArray MyDataArr = [[NSMutableArray alloc]init];//!!!!這裏應該本身初始化數據 self.delegate = self; self.dataSource = self; } //下面兩個是datasource方法 -(NSInteger)numberOfRowsInDDRichText{ return 5; } -(YMTextData *)dataForRowAtIndex:(NSInteger)index{ return [MyDataArr objectAtIndex:0];//!!!!!!!! MyDataArr 是一個YMTextData的數組!!因此你的朋友圈數據的每一項都必須是YMTextData或者繼承YMTextData的子類!! } //下面全部都是delegate的方法 朋友圈全部的特性都使用如下的delegate方法進行控制 方法有可選和必選的 可自行實現 接口調用簡單 -(NSString *)senderName{ return @"David"; } -(BOOL)hideReplyButtonForIndex:(NSInteger)index{ return NO; } -(void)didPromulgatorNameOrHeadPicPressedForIndex:(NSInteger)index name:(NSString *)name{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"發佈者回調" message:[NSString stringWithFormat:@"姓名:%@\n index:%d",name,index] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alert show]; } -(void)didRichTextPressedFromText:(NSString*)text index:(NSInteger)index{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"正文富文本點擊回調" message:[NSString stringWithFormat:@"點擊的內容:%@\n index:%d",text,index] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alert show]; } -(void)didRichTextPressedFromText:(NSString *)text index:(NSInteger)index replyIndex:(NSInteger)replyIndex{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"評論的富文本點擊回調" message:[NSString stringWithFormat:@"點擊的內容:%@\n index:%d \n replyIndex:%d",text,index,replyIndex] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alert show]; } -(void)replyForIndex:(NSInteger)index replyText:(NSString*)text{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"回覆的回調" message:[NSString stringWithFormat:@"回覆的內容:%@\n index:%d",text,index] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alert show]; } @end
效果以下
圖5
博主對WXViewController的改動仍是頗多的,不僅僅是簡單地封裝,我還作了表情和姓名的正則判斷,還對 YMTableViewCell作了大量的邏輯修改,回調的接口作更改和增添也甚多!須要你親自去發現博主隱藏的愛,但不管如何這都是潦草的項目,想要正 式的使用在企業開發中這還遠遠不夠的!沒有進行模塊和單元的測試,其中圖片的處理方式也很差,這裏我是直接要求用戶添加Image文件的 這個應該改爲 添加圖片地址,而後讓這個庫異步去請求顯示的……因此仍是須要你們的開源精神和力量去貢獻本身的,燃燒本身的,騷年文章結束了