一处重复代码的改进(封装无数据情况)

背景

在APP中列表是一种比较常见的数据展示方式,当有数据时,就显示数据;如果没有数据,一般不会显示一个空白页面,而是在空白页面上加一些提示信息,比如像下面这样:

no_message.png
no_message.png

不同的APP会有不同的设计,但不管是什么样的设计,它在整个APP内部应该是一致的,要变也只是文字或图片稍有不同。

现状

因为我们目前的项目还算比较庞大,所以这种列表无数据的情况出现了20多次,所以类似下面的代码出现了就有20多次。为什么说类似,因为是由不同的人写的,逻辑也是差不多,但真的各不相同,有的封装成一个方法,比如:setNoMessageView,有的直接写在viewDidLoad里面......

 - (void)setNoMessageView
 {
     self.noInfoView = [[UIView alloc] initWithFrame:CGRectMake(0, 45, SCREEN_WIDTH, SCREEN_HEIGHT)];
     self.noInfoView.backgroundColor = [UIColor clearColor];
     [self.view addSubview:self.noInfoView];

     UIImageView *carImageView = [[UIImageView alloc] initWithFrame:CGRectMake((SCREEN_WIDTH-120)/2, 60, 120, 86)];
     [carImageView setImage:[UIImage imageNamed:@"no_message.png"]];
     [self.noInfoView addSubview:carImageView];

     UILabel *noInfoLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 160, SCREEN_WIDTH, 20)];
     noInfoLabel.textAlignment = NSTextAlignmentCenter;
     noInfoLabel.textColor = LCRGBColor(211, 211, 211);
     noInfoLabel.text = NSLocalizedString(@"Dear, no information", nil);
     noInfoLabel.backgroundColor = [UIColor clearColor];
     noInfoLabel.font = [LCFont systemFontOfSize:20];
     [self.noInfoView addSubview:noInfoLabel];
 }

先不考虑重复的问题,只是孤立的看上述代码,它也有一些问题:

  • self.noInfoView的frame应该视根据上下文获得的,而不是和屏幕大小绑定,而且yOffset是45也是不对的。
  • carImageView的frame是固定大小的,而图片有可能变。

第一个解决办法

因为创建noInfoView的代码基本差不多,我们可以封装出一个Util方法。

+ (UIView*)createNoMessageViewWithFrame:(CGRect)frame image:(UIImage*)image text:(NSString*)text
{
    UIView* noMessageView = [[UIView alloc] initWithFrame:frame];
    noMessageView.backgroundColor = [UIColor clearColor];

    UIImageView *carImageView = [[UIImageView alloc] initWithFrame:CGRectMake((frame.size.width-image.size.width)/2, 60, image.size.width, image.size.height)];
    [carImageView setImage:image];
    [noMessageView addSubview:carImageView];

    UILabel *noInfoLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 160, frame.size.width, 20)];
    noInfoLabel.textAlignment = NSTextAlignmentCenter;
    noInfoLabel.textColor = LCRGBColor(211, 211, 211);
    noInfoLabel.text = text;
    noInfoLabel.backgroundColor = [UIColor clearColor];
    noInfoLabel.font = [LCFont systemFontOfSize:20];
    [noMessageView addSubview:noInfoLabel];

    return noMessageView;
}

调用:

- (void)setNoMessageView
{
    CGRect rect = self.shopListView.frame;
    UIImage* image = [UIImage imageNamed:@"no_message.png"];
    NSString* text = NSLocalizedString(@"Dear, no information", nil);
    self.noInfoView = [HJUIUtil createNoMessageViewWithFrame:rect image:image text:text];
    [self.view addSubview:self.noInfoView];
}

这样改看起来好多了,把共性封装,把差异作为接口留出。然后其他地方原本要写20行代码,现在只要写5行,而且多个地方调用的代码不会有太大的出入,便于阅读和理解。

第二个解决办法

上面的办法已经不错了,不过除了写5行代码之外,还给ViewController增加了一个属性:noInfoView。现在仔细想一下noInfoView出现的原因,是因为TableView没有内容显示的时候,noInfoView才显示出来,否则就隐藏。可见,这个noInfoView和TableView是紧密联系的,我们可以从UITableView的状态得出noInfoView的状态。那为什么不把它绑定到UITableView上呢?好,那就给UITableView增加一个属性,叫做emptyView。

给一个系统的类增加属性不是那么的简单,但是只要看过SVPullToRefresh的代码,就知道怎么做了。
首先,给UITableView增加一个Category。

@interface UITableView(EmptyView)

@property (nonatomic, strong, readonly) UIView *emptyView;

-(void)addEmptyViewWithImageName:(NSString*)imageName title:(NSString*)title;

@end
static char UITableViewEmptyView;

@implementation UITableView(EmptyView)

@dynamic emptyView;

- (UIView *)emptyView
{
    return objc_getAssociatedObject(self, &UITableViewEmptyView);
}

- (void)setEmptyView:(UIView *)emptyView
{
    [self willChangeValueForKey:@"HJEmptyView"];
    objc_setAssociatedObject(self, &UITableViewEmptyView,
                             emptyView,
                             OBJC_ASSOCIATION_ASSIGN);
    [self didChangeValueForKey:@"HJEmptyView"];
}


-(void)addEmptyViewWithImageName:(NSString*)imageName title:(NSString*)title
{
    if (!self.emptyView)
    {
        CGRect frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
        UIImage* image = [UIImage imageNamed:imageName];
        NSString* text = title;

        UIView* noMessageView = [[UIView alloc] initWithFrame:frame];
        noMessageView.backgroundColor = [UIColor clearColor];

        UIImageView *carImageView = [[UIImageView alloc] initWithFrame:CGRectMake((frame.size.width-image.size.width)/2, 60, image.size.width, image.size.height)];
        [carImageView setImage:image];
        [noMessageView addSubview:carImageView];

        UILabel *noInfoLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 160, frame.size.width, 20)];
        noInfoLabel.textAlignment = NSTextAlignmentCenter;
        noInfoLabel.textColor = LCRGBColor(211, 211, 211);
        noInfoLabel.text = text;
        noInfoLabel.backgroundColor = [UIColor clearColor];
        noInfoLabel.font = [LCFont systemFontOfSize:20];
        [noMessageView addSubview:noInfoLabel];

        [self addSubview:noMessageView];

        self.emptyView = noMessageView;
    }

}

@end

然后外部调用就很简单了,没有额外的属性,而且一句话就搞定。

[self.shopListView.shopListTableView addEmptyViewWithImageName:@"no_message.png" title:@"Dear, no information"];
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值