教你写能被舒服舒服又舒服地调用的IOS库

目录

前言

脑洞开一开

分析

整容

结语

前言

2014年过的那么快,过年又那么块,2015年又是飞快地节奏,真尼玛感觉上帝是不是无聊使用了变速外挂开启了加速模式~到现在博主都无法接受已经上班的事实……在地铁脸被挤在玻璃上的时候只能用眼神写满傻X射这个世界一脸!!原谅博主那么鸡粪~因为哥最近生病了,不嗨心~~,我想来去想不明白,博主每周健身4天,胸肌压女友、拳头比沙煲、吃喝健又康、体硬似野马,怎么会生病呢?我苦思多日,终于有一天早上起床看了镜子半个小时后我才顿悟,我靠~原来长得帅真的是错!上帝在嫉妒我才让我生病的~哈哈哈 咳咳~这是一个严肃的技术博客~是绝对拒绝恶俗低下的内容的,大丈夫应该心系天下才对,最近柴静和雾霾真的触动了我们每个人的心;某极端组织像嗨大了一样,真的是屠龙宝刀在手,装备任爆的节奏;近下的港岛撑完雨伞又要赶人了……我真的是非常痛心疾首,维护世界和平一直是鄙人的愿望,现在的世界这么混乱,本人真的很惭愧,都怪我咯~~没有因为什么,所以今天博主要教大家怎么写一个自己用着安逸,修改巴适,他人用起来又无比舒服的IOS库!!

脑洞开一开

本人不才,接触代码的世界时间真心不是很久,对于系统底层优化、框架级别设计、设计模式的效率优劣等方面的学习和研究比不深刻,所以如果你是大神,你狠溜的话,我还是建议您路过呵呵一下然后就关了这个网页吧,雕虫小技无法入尔法眼啊~我不是怕被喷很菜(反正都被老师喷了二十年了……^_^)而是我对大神都是有敬畏之心的,不能说让你看你就看,你可以试一下是吧,你也不喜欢看完后是Duang 那么多特效 特技……咳咳 反正这篇文章真的很菜~~~适合比我菜的菜鸟,慎读。

不过嘛我们要写一个库,能够让别人用,用起来要很舒服的,那肯定得要设计得当,肯定要熟悉平台,设计模式非常溜才行,这个没错~但是平台、架构、设计这个东西这么复杂,我解释大家也不懂,那我就不解释了(你强迫症发作死都要懂可自行找一个大学,里面有老师~)

我发誓不扯BB了 我们一起来写一个能被舒服舒服又舒服地调用的IOS库,最近卫生纸涨价了,好烦,其实也是有原因的,因为毕竟生产费用什么的也都…我头上的砖头谁扔的!!??信不信我不打死你丫的……

假设我们要开发一个像微信朋友圈或者微博这玩意儿的东西,并且要有能隐藏和展开正文、正文中能够识别富文本(网址、电话、@姓名……)、还要有图片缩略图而且点击查看、能够有回复、回复文中也要支持富文本……这些功能。像这样
图1

所谓君子生非异也 善假于物也。上面的功能这么多这么复杂自己写,你确定你不是吃饱了撑着?经理也说要敏捷开发,所以二话不说闪现到code4app,code.cocoachina祭出最强杀器——搜索引擎,找到了这个库WFCoretext https://github.com/TigerWf/WFCoretext发现它完美符合我们的需求呀,棒棒哒

分析

首先我们感谢WFCoretext 的作者的开源贡献,请收下我的膝盖,我们马上来用一用~
图2

槽点不多
我们来分析分析它怎么搞得把
工程结构 图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

//
// TestViewController.m
// WFCoretext
//
// Created by David on 15/2/7.
// Copyright (c) 2015年 tigerwf. All rights reserved.
//

#import "TestViewController.h"

@interface TestViewController ()

@end

@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

项目及Demo地址:https://github.com/daiweilai/DDRichText

结语

博主对WXViewController的改动还是颇多的,不单单是简单地封装,我还做了表情和姓名的正则判断,还对YMTableViewCell做了大量的逻辑修改,回调的接口做更改和增添也甚多!需要你亲自去发现博主隐藏的爱,但无论如何这都是潦草的项目,想要正式的使用在企业开发中这还远远不够的!没有进行模块和单元的测试,其中图片的处理方式也不好,这里我是直接要求用户添加Image文件的 这个应该改成 添加图片地址,然后让这个库异步去请求显示的……所以还是需要大家的开源精神和力量去贡献自己的,燃烧自己的,骚年文章结束了

时间: 2024-11-10 13:48:13

教你写能被舒服舒服又舒服地调用的IOS库的相关文章

【转】快速开发平台:大湿教我写程序(3)之自动补全(屌丝没有春天)篇

一.女神也爱玩撸码 "在么,亲." "在!在!有,有事么"(我真睡醒了么!垂涎了好久的女神呀!高中同学,高一向她表白,"我想找个170以上的",高二等我长到170了"我想找个175的",高三下血本买了双内增高"我喜欢178以上的,有安全感") 三分钟后.... "没事也可找我的."擦,我TM怎么这么不争气,不是发过誓等她主动跟我讲话的时候就送她一个字:滚! "有个网页不会做,你

Android开发之手把手教你写ButterKnife框架(二)

欢迎转载,转载请标明出处: http://blog.csdn.net/johnny901114/article/details/52664112 本文出自:[余志强的博客] 上一篇博客Android开发之手把手教你写ButterKnife框架(一)我们讲了ButterKnife是什么.ButterKnife的作用和功能介绍以及ButterKnife的实现原理. 本篇博客主要讲在android studio中如何使用apt. 一.新建个项目, 然后创建一个module名叫processor 新建m

手把手教你写Sublime中的Snippet

手把手教你写Sublime中的Snippet Sublime Text号称最性感的编辑器, 并且越来越多人使用, 美观, 高效 关于如何使用Sublime text可以参考我的另一篇文章, 相信你会喜欢上的..Sublime Text 2使用心得 现在介绍一下Snippet, Snippets are smart templates that will insert text for you and adapt it to their context. Snippet 是插入到文本中的智能模板并

手把手教你写专利申请书/怎样申请专利

手把手教你写专利申请书·怎样申请专利 摘要小前言(一)申请前的准备工作    1.申请前查询    2.其它方面的考虑    3.申请文件准备(二)填写专利申请系列文档    1.实际操作步骤    2.详细操作    3.经验分享.注意事项(三)关于费用(四)其它的话參考资源提示常见问题的问与答 摘要: 怎样写好专利申请?由于非常多专利申请人都是第一次申请,因此,可能有一种神奇和些许恐惧.本文写的是怎样写专利申请书,手把手教你写专利申请并提供申请专利时的注意事项,专利申请费用及费用减缓等相关參

手把手教你写Windows 64位平台调试器

本文网页排版有些差,已上传了doc,可以下载阅读.本文中的所有代码已打包,下载地址在此. -------------------------------------------------------------------------------------------------------------------------------------------------------------- 手写一个调试器有助于我们理解hook.进程注入等底层黑客技术具体实现,在编写过程中需要涉及大

手把手教你写电商爬虫-第三课 实战尚妆网AJAX请求处理和内容提取

系列教材: 手把手教你写电商爬虫-第一课 找个软柿子捏捏 手把手教你写电商爬虫-第二课 实战尚妆网分页商品采集爬虫 看完两篇,相信大家已经从开始的小菜鸟晋升为中级菜鸟了,好了,那我们就继续我们的爬虫课程. 上一课呢一定是因为对手太强,导致我们并没有完整的完成尚妆网的爬虫. 吭吭~,我们这一课继续,争取彻底搞定尚妆网,不留任何遗憾. 我们先回顾一下,上一课主要遗留了两个问题,两个问题都和ajax有关. 1.由于是ajax加载下一页,导致下一页url并不会被系统自动发现. 2.商品页面的价格是通过a

手把手教你写电商爬虫-第四课 淘宝网商品爬虫自动JS渲染

系列教程: 手把手教你写电商爬虫-第一课 找个软柿子捏捏 手把手教你写电商爬虫-第二课 实战尚妆网分页商品采集爬虫 手把手教你写电商爬虫-第三课 实战尚妆网AJAX请求处理和内容提取 老规矩,爬之前首先感谢淘宝公布出这么多有价值的数据,才让我们这些爬虫们有东西可以搜集啊,不过淘宝就不用我来安利了 广大剁手党相信睡觉的时候都能把网址打出来吧. 工欲善其事,必先利其器,先上工具: 1.神箭手云爬虫,2.Chrome浏览器 3.Chrome的插件XpathHelper 不知道是干嘛的同学请移步第一课

手把手教你写电商爬虫-第五课 京东商品评论爬虫 一起来对付反爬虫

系列教程: 手把手教你写电商爬虫-第一课 找个软柿子捏捏 手把手教你写电商爬虫-第二课 实战尚妆网分页商品采集爬虫 手把手教你写电商爬虫-第三课 实战尚妆网AJAX请求处理和内容提取 手把手教你写电商爬虫-第四课 淘宝网商品爬虫自动JS渲染 四节课过去了,咱们在爬虫界也都算见过世面的人,现在再来一些什么ajax加载之类的小鱼小虾应该不在话下了,即使是淘宝这种大量的ajax,我们 祭上我们的核武器,也轻松应对了,这一课主要是来看看除了技术上的页面处理外,我们还会遇上更棘手的问题,就是反爬虫,当然现

iOS动画进阶 - 手摸手教你写 Slack 的 Loading 动画

如果移动端访问不佳,可以访问我的个人博客 前几天看了一篇关于动画的博客叫手摸手教你写 Slack 的 Loading 动画,看着挺炫,但是是安卓版的,寻思的着仿造着写一篇iOS版的,下面是我写这个动画的分解~ 老规矩先上图和demo地址: 刚看到这个动画的时候,脑海里出现了两个方案,一种是通过drawRect画出来,然后配合CADisplayLink不停的绘制线的样式:第二种是通过CAShapeLayer配合CAAnimation来实现动画效果.再三考虑觉得使用后者,因为前者需要计算很多,比较复