美文网首页
iOS开发 - 链式编程的应用X_Kit

iOS开发 - 链式编程的应用X_Kit

作者: 来者可追文过饰非 | 来源:发表于2019-03-18 11:25 被阅读0次
1.发现问题

假如我们写一个UILabel,我们的代码会可能会如下所示

    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
    label.text = @"Hello world!";
    label.textColor = [UIColor whiteColor];
    label.font = [UIFont systemFontOfSize:15];
    label.textAlignment = NSTextAlignmentCenter;
    label.backgroundColor = [UIColor redColor];
    label.layer.cornerRadius = 25;
    label.clipsToBounds = YES;
    [self.view addSubview:label];

这段代码有什么问题呢? 没错!就是非常臃肿,像这些简单的模块如果不加以封装,项目中代码量将会非常多,既不利于阅读,也不利于维护.

2.初步封装

在分类中添加方法

// .h
+ (UILabel *)labelWithText:(NSString *)text textColor:(UIColor *)color font:(UIFont *)font textAlign:(NSTextAlignment)align bgColor:(UIColor *)bgColor cornerRadius:(CGFloat)radius .......;

// .m
+ (UILabel *)labelWithText:(NSString *)text textColor:(UIColor *)color font:(UIFont *)font textAlign:(NSTextAlignment)align bgColor:(UIColor *)bgColor cornerRadius:(CGFloat)radius ....... {
    UILabel *label = [[UILabel alloc] init];
    label.text = text;
    label.textColor = color;
    ...
    return label;
}

这样的话,我们每次在初始化一个控件的时候,只需要1行代码就可以基本完成问题.但是这样写也有一个新的问题,就是可拓展性的问题.
-----假如我们只需要设置text和textColor,我们需要写上这么一行,然后后边参数传空
-----假如我们需要另外设置numOfLines或者其他没有封装到的属性,我们也需要写上这么一行,然后额外设置其他属性

3.继续优化

最近再看Masonry源码,其中的链式编程思想对我有很大的启发,我想是否可以采用block的形式设置属性,并用链式编程将他它们链接起来呢?
说干就干!
.h文件

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

typedef UILabel* (^xl_Block)(id);

@interface UILabel (X)

@property (nonatomic, copy, readonly) xl_Block x_text;
@property (nonatomic, copy, readonly) xl_Block x_font;
@property (nonatomic, copy, readonly) xl_Block x_textColor;
@property (nonatomic, copy, readonly) xl_Block x_align;


@property (nonatomic, copy, readonly) xl_Block x_numOfLines;
@property (nonatomic, copy, readonly) xl_Block x_shadowOffset;
@property (nonatomic, copy, readonly) xl_Block x_lineBreakMode;
@property (nonatomic, copy, readonly) xl_Block x_attributedText;

@end

NS_ASSUME_NONNULL_END

.m文件

#import "UILabel+X.h"
#import "XKit.h"
@implementation UILabel (X)

- (xl_Block)x_text
{
    xl_Block block = ^UILabel* (NSString *text) {
        self.text = text;
        return self;
    };
    return block;
}

- (xl_Block)x_font {
    xl_Block block = ^UILabel* (UIFont *font) {
        self.font = font;
        return self;
    };
    return block;
}

- (xl_Block)x_textColor {
    xl_Block block = ^UILabel* (UIColor *color) {
        self.textColor = color;
        return self;
    };
    return block;
}

- (xl_Block)x_align {
    xl_Block block = ^UILabel* (NSNumber *align) {
        self.textAlignment = align.integerValue;
        return self;
    };
    return block;
}

- (xl_Block)x_numOfLines {
    xl_Block block = ^UILabel* (NSNumber *num) {
        self.numberOfLines = num.integerValue;
        return self;
    };
    return block;
}

- (xl_Block)x_shadowOffset {
    xl_Block block = ^UILabel *(NSValue *value) {
        self.shadowOffset = value.CGSizeValue;
        return self;
    };
    return block;
}

- (xl_Block)x_lineBreakMode {
    xl_Block block = ^UILabel *(NSNumber *mode) {
        self.lineBreakMode = mode.integerValue;
        return self;
    };
    return block;
}

- (xl_Block)x_attributedText {
    xl_Block block = ^UILabel *(NSAttributedString *attr) {
        self.attributedText = attr;
        return self;
    };
    return block;
}
@end

这样,我们的代码便可以这样写

    UILabel *label = [UILabel new];
    label
    .x_text(@"Hello world!")
    .x_textColor([UIColor whiteColor])
    .x_font([UIFont systemFontOfSize:15])
    .x_align(@(NSTextAlignmentCenter))
    .x_sizeToFit(@(YES));
    
    label
    .x_cornerRadius(@(15))
    .x_clipToBounds(@(YES))
    .x_backgroundColor([UIColor redColor]);
    [self.view addSubview:label];

是不是很神奇😆

4.项目地址

具体源码可以去我的github上下载
前往github
希望大家多提意见和建议,可以的话给个小星星奖励

5.存在的问题

1.以UILabel 和 UIView为例
写分类方法的时候,我将
UILabel的属性写到UILabel+X中,其中block返回的为UILabel对象
UIView的属性写到UIView+X中,其中的block返回的为UIView对象
所以就会出现例如label.x_backgroundColor([UIColor whiteColor]) 之后再去调用UILabel的属性后报错的情况

目前暂时的解决方法:写的时候要先写UILabel的属性,再写UIView的属性,例如:

    UILabel *label = [UILabel new];
    label
    .x_text(@"Hello world!")
    .x_textColor([UIColor whiteColor])
    .x_font([UIFont systemFontOfSize:15])
    .x_align(@(NSTextAlignmentCenter))
    .x_sizeToFit(@(YES));
    // 上边为UILabel的属性,下边为父类UIView的属性
    .x_cornerRadius(@(15))
    .x_clipToBounds(@(YES))
    .x_backgroundColor([UIColor redColor]);
    [self.view addSubview:label];

2.以UITableView为例,如果想使用链式及block的形式实现UITableView的代理方法,便会自动设置delegate 和 datasource为当前的tableview,并走UITableView+X中实现的delegate 和 datasource方法,之前设置的delegate 和 dataSource 将会无效,例如:

UITableView *table = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
    table
    .x_rowHeight(@60)
    .x_sectionHeaderHeight(@0.01)  // 在iOS11之后需要设置该属性,才会走heightForHeader的代理方法
    .x_sectionFooterHeight(@0.01) // 在iOS11之后需要设置该属性,才会走heightForFooter的代理方法
    .x_registerCell([UITableViewCell class], cellID)
    .x_delegate(self)
    .x_dataSource(self)
    // 如果实现了delegate 或者 datasource的block,就会自动设置当前为delegate和datasource为table本身,并走UITableView+X中实现的delegate 和 datasource方法,之前设置的delegate 和 dataSource 将会无效
    .x_viewForHeaderInSection(^UIView * _Nonnull(UITableView * _Nonnull table, NSInteger section) {
        UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, UIScreen.mainScreen.bounds.size.width, 200)];
        header.backgroundColor = [UIColor redColor];
        return header;
    })
    .x_viewForFooterInSection(^UIView * _Nonnull(UITableView * _Nonnull table, NSInteger section) {
        UIView *footer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, UIScreen.mainScreen.bounds.size.width, 200)];
        footer.backgroundColor = [UIColor blueColor];
        return footer;
    })
    .x_heightForFooterInSection(^NSInteger(UITableView * _Nonnull table, NSInteger section) {
        return 20;
    })
    .x_heightForHeaderInSection(^NSInteger(UITableView * _Nonnull table, NSInteger section) {
        return 20;
    })
    .x_numofSectionsInTableView(^NSInteger(UITableView * _Nonnull table) {
        return self.dataSource.count;
    })
    .x_numOfRowsInSection(^NSInteger(UITableView * _Nonnull table, NSInteger section) {
        return [self.dataSource[section] count];
    })
    .x_cellForRowAtIndexPath(^UITableViewCell * _Nonnull(UITableView * _Nonnull table, NSIndexPath * _Nonnull indexpath) {
        UITableViewCell *cell = [table dequeueReusableCellWithIdentifier:cellID forIndexPath:indexpath];
        cell.textLabel.text = self.dataSource[indexpath.section][indexpath.row];
        return cell;
    })
    ;
    
    [self.view addSubview:table];

3.后续我们持续更新该框架,感谢大家支持!

相关文章

  • iOS开发 - 链式编程的应用X_Kit

    1.发现问题 假如我们写一个UILabel,我们的代码会可能会如下所示 这段代码有什么问题呢? 没错!就是非常臃肿...

  • ReactiveObjC入门

    ReactiveObjC基础用法 iOS开发三种编程方式(响应式编程、函数编程、链式编程),函数编程最常用,链式编...

  • iOS-链式编程思想

    在iOS中,链式编程虽然用的不太多,但是,在特定的应用环境下,利用block实现链式编程的话,会大大的提高编程效率...

  • iOS链式编程

    在iOS中,链式编程虽然用的不太多,但是,在特定的应用环境下,利用block实现链式编程的话,会大大的提高编程效率...

  • 工作iOS技术总结

    链式编程、函数式、面向接口编程思想 iOS 之ReactiveCocoa 链式编程2 WKWebView的缓存处理...

  • iOS开发Masonry框架源码解析

    iOS开发Masonry框架源码解析 前言:这个框架编程思想主要包括链式编程 这是一个iOS在控件布局中的轻量级框...

  • ios开发-链式编程

    什么是链式编程,我看到这个东西第一反应,这不就是一个装饰模式嘛,其实我的理解,链式编程就是一个写法特别的装饰模式,...

  • 一、链式编程思想、响应式编程思想和函数式编程

    1. 链式编程思想 链式编程思想的核心就是方法的返回值必须是Block,Masonry是链式编程思想应用的代表。 ...

  • RAC学习详解

    Block开发基础知识 链式编程思想简介 响应式编程思想简介 函数式编程思想简介 参考资料 iOS 关于MVC和M...

  • 链式编程总结

    链式编程总结 @(iOS) 研究了一下链式编程,但是感觉项目中用处不是很多。 介绍 1.什么时候使用链式编程?在面...

网友评论

      本文标题:iOS开发 - 链式编程的应用X_Kit

      本文链接:https://www.haomeiwen.com/subject/liammqtx.html