分享最热门的资讯
前言
前两篇分享了一下多线程和动画的内容.一直本着一篇都能讲全一个知识模块的原则,下一篇打算分享一下runtime的大部分api.
名字先想好了:
上面两篇都还没写不要点...
开始正题.今天这篇主要有三个目的:
分享一个简单点的小项目为下篇iOS-runtime通篇详解和下下篇iOS-第三方框架中看似牛逼的宏打基础.
讲解一下这个工具集的基本用法
希望能帮助小伙伴们提高开发效率
给自己的框架宣传一下,希望更多人可以用,另外也希望大家一起来丰富这个工具集,共同进步.
先把这个框架的地址贴出来:TFEasyCoder
废话先说到这里,我们先看下TFEasyCoder是个什么东西,有什么作用:
TFEasyCoder简介:
简单点说它是一个可以帮助还在用oc的同学提高开发效率和改善代码美观性的一个工具性框架.
它的主要几个功能:
1. 为所有UIKit,Foundition类添加了一系列的可以提高开发速度的方法
2. 为所有UIKit,Foundition类的公开可写属性添加了链式编程的方法(如果你不喜欢链式编程,那这个基本没什么用,因为它代码量很大)
3. 提供了一些可以提高开发效率的宏定义
4. 提供了一套同意书写规范的Category工具集(还在开发中,并且不断在完善)
5. 提供了一些开发的调试工具集
6. 以上的所有api调用方式可以个性化定制.
再看下它的目录结构:
TFEasyCoder目录结构.png
目录结构文件说明:
1.这是Masonry
2.项目主要文件
TFEasyCoder.h项目总的.h文件:引入了下面所有的文件,用的时候直接导入这个就可以了.
TFEasyCoderConst.h项目里用到的宏都在这里
NSObject+TFExecute.h
NSObject+TFExecute.m
功能处理文件,不看源码的同学可以忽略.
TFEasyCoder_CA.h
TFEasyCoder_CA.m
TFEasyCoder_UI.h
TFEasyCoder_UI.m
TFEasyCoder_NS.h
TFEasyCoder_NS.m
UIKit,Foundition两大框架所有类的快速创建block方法,下面详细说
3.文件夹tfkit
Category工具集,包含了很多很多常用分类工具方法,下面详细说.
4.文件夹ca(包含23个类文件,共0.4m) foundation(包含160个类文件,共1.9m) uikit(包含168类,共2.3m)
链式编程方法类,下面详细说.
1. 为所有UIKit,Foundition类添加了一系列的可以提高开发速度的方法
举个例子,我们平时使用一个类时可能会这么写:
#import "TmpObject.h" @interface TmpObject () //(1)先定义一个属性 @property (nonatomic,strong)UILabel *titleLabel1; @end @implementation TmpObject -(instancetype)init{ if (self = [super init]) { //(2)然后创建一个类,再把这个类赋给这个属性 UILabel *title1 = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 0, 0)]; title1.text = @"title1"; title1.textColor = [UIColor redColor]; title1.font = [UIFont systemFontOfSize:12]; title1.lineBreakMode = NSLineBreakByCharWrapping; title1.numberOfLines = 0; [self addSubview: title1]; self.titleLabel1 = title1; [self.titleLabel1 mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(weakSelf); make.left.equalTo(weakSelf); make.bottom.equalTo(weakSelf); make.right.equalTo(weakSelf); }]; } return self; } @end
然后如果我们想写不止一个类的时候我们需要做什么工作?
(1)把上面的代码复制一遍
(2)把上面所有的title1都改成title2
(3)把上面所有的self.titleLabel1都改成self.titleLabel2
但是如果我们不这么写还可以怎么写呢?看下面:
上面可能是我们平时写代码的样子,或者是类似这个样子,但是现在就不用这么写了:
#import "TmpObject.h" @interface TmpObject () //(1)先定义一个属性 @property (nonatomic,strong)UILabel *titleLabel1; @property (nonatomic,strong)UILabel *titleLabel2; @end @implementation TmpObject -(instancetype)init{ if (self = [super init]) { kdeclare_weakself; //我们可以这样创建一个类,如果想写大于一个,那么你直接复制下面的代码块就可以了 [UILabel easyCoder:^(UILabel *ins) { ins.text = @"title1"; ins.textColor = [UIColor redColor]; ins.font = [UIFont systemFontOfSize:12]; ins.lineBreakMode = NSLineBreakByCharWrapping; ins.numberOfLines = 0; [ins mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(weakSelf); make.left.equalTo(weakSelf); make.bottom.equalTo(weakSelf); make.right.equalTo(weakSelf); }]; [weakSelf addSubview:ins]; weakSelf.titleLabel1 = ins; }]; } return self; } @end
同样的,如果我们想写不止一个类的时候我们需要做什么工作?
(1)把上面的代码复制一遍
(2)把weakSelf.titleLabel1 = ins;把这句改了,完事
总结上面两段代码对比优势:
(1)UIKit和Foundation中每一个类(共351个类)都提供了两个方法easyCoder
类方法:easyCoder:用于快速创建一个类并将其在block中(ins)和方法返回值label将其返回(一般不建议用方法返回值接,因为写代码又要多费一步);
TFEasyCoder代码(2).png
实例方法:easyCoder:用于快速操作一个已有的对象:
TFEasyCoder代码(3).png
(2)比传统写代码的方式,复制起来速度更快,更不容易出错,代码更整洁
(3)重要的事情说三遍:
以上代码块中出现的easyCoder和ins全都是可以改的!
以上代码块中出现的easyCoder和ins全都是可以改的!
以上代码块中出现的easyCoder和ins全都是可以改的!
在这里改:
TFEasyCoder代码(4).png
如果想把上面示例代码中的ins(instance的意思)改了你就改红圈圈住的ins如果想把上面示例代码中的easyCoder改了你就改红圈圈住的easyCoder
在这里改完以后所有类的调用方法和block内返回的对象名都会改的,xcode的智能提示也会改.比如说我想把easyCoder改成sha_bi_chan_pin,然后把ins改成chi_shi你写代码的时候就会像下面这样:
TFEasyCoder代码(5).gif
这样写是不是比较爽?(上面的纯属娱乐,请产品小伙伴不要认真)
截止到现在这个工具集其中的一个小功能就算讲完了,上面的代码量不小但是没什么技术难度,那么我们继续往下看更多好玩且实用的功能~
实例的私有和公有属性赋值方法
这里提供了为类赋值的方法,使用方式如下:
TFEasyCoder代码(6).png
注意:上面那句可以为私有属性和共有属性赋值,并且它和下面这句话是不同的
TFEasyCoder代码(7).png
上面两句的不同点在于前者可以赋值成功,后者是不可以的,因为它内部并不会对属性值转换类型.
另外:你还可以用这个方法对于性赋值进行链式形式写代码比如下面这样:
TFEasyCoder代码(8).png
以上代码块中出现的语法set_ValueKey也是是可以改的具体改法参照上面讲的就可以了.
2. 为所有UIKit,Foundition类的公开可写属性添加了链式编程的方法(如果你不喜欢链式编程,那这个基本没什么用,因为它代码量很大)
直接看代码吧:
TFEasyCoder代码(9).png
这样就给UILable的6个属性赋值了
也可以写成下面这样好复制:
TFEasyCoder代码(10).png
上面其实是一行代码,只是换行了看起来好看而已.
总结
这个功能其实性其实并不高.因为它的源码的代码量其实是很大的(总共4.6m),而且实现的功能也只是可以用链式语法调用而已,所以建议不喜欢链式语法的小伙伴不要用了还是.
属性的链式写法不同于上面,这里的语法是不可以改的都是前缀set_+属性名,因为改语法需要用到宏,但是因为这些文件代码量巨大,如果都用宏写的话会严重拖慢编译速度,所有都写成了纯代码形式,所以它不可以改.(如果你非要改的话可以用xcode把set_全局替换了就可以了)
3. 提供了一些可以提高开发效率的宏定义
现在还不是很多,以后会慢慢完善,先一个个看吧:
为分类添属性
#import "NSObject+TestCategory.h" typedef void(^EasyCoderBlock) (void); @interface NSObject () @property (nonatomic, copy)NSString *string; @property (nonatomic, copy)EasyCoderBlock block; @property (nonatomic,assign)id delegate; @property (nonatomic,strong)NSMutableArray *dataSource; @property (nonatomic,assign)CGRect frame; @property (nonatomic,strong)NSNumber *isSelected; @end @implementation NSObject (TestCategory) //为copy类型属性添加实现: string为getter方法名,setString为setter方法名 TF_SYNTHESIZE_CATEGORY_PROPERTY_COPY(string, setString); //为block类型属性添加实现:前两个参数同上,第三个参数为block类型 TF_SYNTHESIZE_CATEGORY_PROPERTY_BLOCK(block, setBlock, EasyCoderBlock); //为assign类型属性添加实现:同上 TF_SYNTHESIZE_CATEGORY_PROPERTY_ASSIGN(delegate, setDelegate); //为strong类型属性添加实现:同上 TF_SYNTHESIZE_CATEGORY_PROPERTY_RETAIN(dataSource, setDataSource); //为特殊类型属性添加实现(比如stuct):前两个参数同上,第三个参数为数据类型的ctype TF_SYNTHESIZE_CATEGORY_PROPERTY_CTYPE(frame, setFrame, typeof(CGRect)); //为自定义类型属性添加实现:前两个参数同上,第三个参数为属性的引用类型,最后一个为属性的类型 TF_SYNTHESIZE_CATEGORY_PROPERTY(isSelected, setIsSelected, OBJC_ASSOCIATION_RETAIN_NONATOMIC, NSNumber*); @end
为你的类添加+-easyCoder方法
//在.h文件中写:其中Tmp2Object类名,Tmp2Object * 是类型 TF_DEFINE_TFEASYCODER_INT(Tmp2Object, Tmp2Object*); //在.m文件中写:其中Tmp2Object类名,Tmp2Object * 是类型 TF_DEFINE_TFEASYCODER_IMP(Tmp2Object, Tmp2Object*);
这样你的类就可以这样调用了:
TFEasyCoder代码(12).gif
属性的懒加载
属性的懒加载有两种方式:
(1)单纯的懒加载
(2)懒加载的时候做一些事情
(1)单纯的懒加载:
TFEasyCoder代码(13).png
如上图,如果我们就是简单的要求属性懒加载上面一句话就可以了.
(2)懒加载的时候做一些事情:
TFEasyCoder代码(14).png
总结
上面两个例子简单来说是为我们减少了一些代码,并不比传统的懒加载写法优秀多少.但是试想如果你需要懒加载的属性非常多的时候你就会多做很多无用功,上面的图就是一个很好的例子.
4. 提供了一套同意书写规范的Category工具集(持续开发中)
因为文件和方法太多,下面拿一个类示范讲一下:
TFEasyCoder代码(15).png
上图应该是我们最常用的一个类了:获取和设置view的相关尺寸,看如下代码
//下面是随便写了几种使用方式 //设置frame的左上角位置 self.view.tf_origin = CGPointMake(0, 0); //设置frame的右下角的位置(固定origin改变size) self.view.tf_rightBottom = CGPointMake(220, 220); //获取frame的左下角点 NSLog(@"self.view.tf_center_x:%@",NSStringFromCGPoint(self.view.tf_leftBottom)); //设置宽度 self.view.tf_width = 100; //设置size self.view.tf_size = CGSizeMake(300, 300);
看上面的代码的一个特点是所有方法都是tf_打头的,再看上面的图screenBounds分别提供了静态方法和实例方法调用.
总结
tfkit是一个Category工具集(目前只有20多个类,还在持续更新中).
这些工具集一共有以下几个特点:
所有的方法如果可以提供静态和实例方法一定会一起提供
所有的实例无参方法一定对应一个属性,以便方便打点调用
如果属性没有标明readonly那么它一定是可读写的
大多数都有注,以后会全部有注释
最重要的一点:
里面所有的方法默认都是有前缀的tf_,但是这个前缀可以删也可以改
里面所有的方法默认都是有前缀的tf_,但是这个前缀可以删也可以改
里面所有的方法默认都是有前缀的tf_,但是这个前缀可以删也可以改
改的方式如下图,把tf_直接改成你想要的前缀所有的方法前缀都可以变了:
TFEasyCoder代码(16).png
5. 提供了一些开发的调试工具集
(1)NSArray和NSDictionary打印中文内容
以前打印字典或者数组是这样的,调试很不方便
/** * 快速操作已有对象 * @param ins 操作对象 * @return 操作对象 */ [self.dataSource easyCoder:^(NSMutableArray *ins) { [ins addObject:@{@"icon":@"home_visitor_icon",@"title":@"我的访客"}]; [ins addObject:@{@"icon":@"home_birthday_icon",@"title":@"好友生日"}]; [ins addObject:@{@"icon":@"home_music_icon",@"title":@"背景音乐"}]; [ins addObject:@{@"icon":@"home_lovers_icon",@"title":@"情侣空间"}]; }]; NSLog(@">>>:%@",self.dataSource); //打印结果: 2016-12-18 23:22:49.348 TFEasyCoderDemo[92905:7531299] >>>:( { icon = "home_visitor_icon"; title = "\U6211\U7684\U8bbf\U5ba2"; }, { icon = "home_birthday_icon"; title = "\U597d\U53cb\U751f\U65e5"; }, { icon = "home_music_icon"; title = "\U80cc\U666f\U97f3\U4e50"; }, { icon = "home_lovers_icon"; title = "\U60c5\U4fa3\U7a7a\U95f4"; } )
现在是这样的:
2016-12-18 23:25:31.072 TFEasyCoderDemo[92982:7536183] >>>:[ { "title" : "我的访客", "icon" : "home_visitor_icon" }, { "title" : "好友生日", "icon" : "home_birthday_icon" }, { "title" : "背景音乐", "icon" : "home_music_icon" }, { "title" : "情侣空间", "icon" : "home_lovers_icon" } ]
使用方式:不用改任何代码,将下面开关设为YES就好了:
TFEasyCoder代码(17).png
(2)设置view的所有子视图显示随机色
先看效果图:
TFEasyCoder代码(18).png
调用方式:
//这是一个view的分类方法 [self.view tf_setAllSubviewsBackgroundColorRandom:0.5];
(3)设置view的所有子视图显示边框
先看效果图:
TFEasyCoder代码(19).png
调用方式:
//这是一个view的分类方法 [self.view tf_setAllSubviewsBorderRed];
(4)打印当前控制器名称
倒入框架后,然后打开打印控制器名字开关,viewDidAppear每次执行的时候都会打印当前控制器的名字,开关打开如下图:
TFEasyCoder代码(20).png
(5)获取view的所有子(或者父)视图
//这里用延迟的原因是,只能获取内存中已存在的视图 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ //获取一个view的所有子视图 NSArray *allsubs = [self.view tf_getAllSubviews]; //NSLog(@">>>>:%@",allsubs); }); //打印结果: 2016-12-18 23:45:23.983 TFEasyCoderDemo[93414:7565791] >>>>:( "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" )
(6)打印view的视图树
调用方式:
/** * 打印当前已存在的视图tree(UI开发工具) */ [self.view tf_logSubviews:^NSArray *{ //这里返回你要在视图tree里面显示的视图属性,返回nil则默认打印 //@[@"frame",@"hidden",@"backgroundColor",@"userInteractionEnabled"] return @[@"frame",@"hidden",@"backgroundColor",@"userInteractionEnabled"]; }];
打印结果比较长,但也比较重要,建议看完:
{
UIView = {
properties = {
backgroundColor = "UIExtendedSRGBColorSpace 1 1 1 1";
frame = "NSRect: {{0, 0}, {375, 667}}";
hidden = 0;
userInteractionEnabled = 1;
};
subviews = (
{
"_UILayoutGuide" = {
properties = {
backgroundColor = null;
frame = "NSRect: {{0, 0}, {0, 20}}";
hidden = 1;
userInteractionEnabled = 1;
};
subviews = (
);
};
},
{
"_UILayoutGuide" = {
properties = {
backgroundColor = null;
frame = "NSRect: {{0, 667}, {0, 0}}";
hidden = 1;
userInteractionEnabled = 1;
};
subviews = (
);
};
},
{
UITableView = {
properties = {
backgroundColor = "UIExtendedGrayColorSpace 0.666667 0.1";
frame = "NSRect: {{0, 0}, {375, 667}}";
hidden = 0;
userInteractionEnabled = 1;
};
subviews = (
{
UITableViewWrapperView = {
properties = {
backgroundColor = null;
frame = "NSRect: {{0, 0}, {375, 667}}";
hidden = 0;
userInteractionEnabled = 1;
};
subviews = (
{
TableviewCell = {
properties = {
backgroundColor = "UIExtendedSRGBColorSpace 1 1 1 1";
frame = "NSRect: {{0, 419}, {375, 48}}";
hidden = 0;
userInteractionEnabled = 1;
};
subviews = (
{
UITableViewCellContentView = {
properties = {
backgroundColor = null;
frame = "NSRect: {{0, 0}, {375, 48}}";
hidden = 0;
userInteractionEnabled = 1;
};
subviews = (
{
UIImageView = {
properties = {
backgroundColor = null;
frame = "NSRect: {{15, 11.5}, {25, 25}}";
hidden = 0;
userInteractionEnabled = 0;
};
subviews = (
);
};
},
{
UILabel = {
properties = {
backgroundColor = "UIExtendedGrayColorSpace 0 0";
frame = "NSRect: {{50, 11.5}, {150, 25}}";
hidden = 0;
userInteractionEnabled = 0;
};
subviews = (
);
};
},
{
UIImageView = {
properties = {
backgroundColor = null;
frame = "NSRect: {{350, 19}, {10, 10}}";
hidden = 0;
userInteractionEnabled = 0;
};
subviews = (
);
};
},
{
&nb
本文由 姬長信 创作,文章地址:https://blog.isoyu.com/archives/1906.html
采用知识共享署名4.0 国际许可协议进行许可。除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。最后编辑时间为:2月 14, 2017 at 04:00 下午