史上最全的DZNEmptyDataSet(空白页框架)说明书

前段时间因为有这么一个需求,就是当页面数据为空时要显示一个基础页面,引导用户进行刷新,故找到DZNEmptyDataSet作为我们的基础框架使用,在这里跟大家介绍下它的简单用法,欢迎交流,喜欢的同学记得点赞哦。

写在前面

DZNEmptyDataSet是一个下拉式的UITableView/UICollectionView父类,在列表没有内容要显示时使用Empty DataSet模式。
比如:大多数应用程序都会显示内容列表(datasets),但是某些情况下可能会是空的,尤其是新用户的账户信息。一旦产生错误或bug,空白屏幕会使用户困惑,不知道要做什么,所以Empty DataSet模式可以给用户提示相关信息。

一:概述

作用

- 精简开发人员处理列表为空的操作
- 提高应用中出现列表空白的交互体验

功能

- 应用列表出错或无数据时显示提示
- 可自定义列表空白时显示的背景颜色、视图及垂直和水平对齐
- 可自定义布局外观
- 可自定义动画
- 支持点击手势(按钮或视图)

优点

- 避免白屏,告诉用户屏幕为何为空;
- 提示用户下一步的操作;
- 避免其它中断机制,比如显示错误提醒;
- 保持连续性,改善用户体验;
- 展示品牌标示。

兼容

- UITableView
- UICollectionView
- UISearchDisplayController
- UIScrollView

- storyBoard
- iOS 6 ~
- iPhone,iPad,苹果电视

可行性

在ios开发中,tableview和collectionview是非常常用的控件,在开发中为了提高交互体验,我们会对列表为空或数据请求错误的时候显示一个视图以提示用户。如果在controller中通过代码控制提示视图的显示和隐藏,会显得繁杂不好控制,可维护性低。该库通过协议代理模式把提示视图的逻辑提炼出来,简单易用,可定制性高,提高了代码的维护性和可读性。

方法简介

DataSource:数据源方法

空白页的标题

注:
1:该标题并不是页面的标题,是提示视图的标题
2:必须返回富文本(可设置其颜色,字号,风格等。或:nil)
   如:
   NSString * title = [NSString stringWithFormat:@"洪荒之力"];
   return [[NSAttributedString alloc] initWithString:title attributes:nil];

- (NSAttributedString *)titleForEmptyDataSet:(UIScrollView *)scrollView;

空白页正文

注:
必须返回富文本(可设置其颜色,字号,风格等。或:nil,方法同上)
- (NSAttributedString *)descriptionForEmptyDataSet:(UIScrollView *)scrollView;

空白页图片

注:
如果直接返回图片,显示的图片会是图片原本的尺寸。可以在该方法中重置图片大小再return。
- (UIImage *)imageForEmptyDataSet:(UIScrollView *)scrollView;

空白页图片的色调

注:
该方法一般不用,默认为nil
- (UIColor *)imageTintColorForEmptyDataSet:(UIScrollView *)scrollView;

空白页图片(视图)动画

注:
该方法是设置图片或视图的动画,可设置动画组CAAnimationGroup
- (CAAnimation *) imageAnimationForEmptyDataSet:(UIScrollView *) scrollView;

空白页中按钮上文本

注:
1:该方法设置按钮上的文字
2:必须返回富文本
3:state:按钮点击状态。UIControlState中按需选择
4:该方法只是返回按钮文字,可结合一下方法设置按钮背景样式
   - (UIImage *)buttonImageForEmptyDataSet:(UIScrollView *)scrollView forState:(UIControlState)state;
   - (UIImage *)buttonBackgroundImageForEmptyDataSet:(UIScrollView *)scrollView forState: (UIControlState)state;

- (NSAttributedString *)buttonTitleForEmptyDataSet:(UIScrollView *)scrollView forState:(UIControlState)state;

设置按钮前景图

注:
该方法设置的是按钮的前景图,所以,图片将会覆盖(buttonTitleForEmptyDataSet)方法返回的文本。源码中:先判断是否有前景图,如果没有,才设置文本。
- (UIImage *)buttonImageForEmptyDataSet:(UIScrollView *)scrollView forState:(UIControlState)state;

设置按钮背景图

注:
1:state:按钮点击状态。UIControlState中按需选择
- (UIImage *)buttonBackgroundImageForEmptyDataSet:(UIScrollView *)scrollView forState:(UIControlState)state;

设置空白页背景颜色

注:
1:默认为clear,无色,即会显示所在controller背景色
- (UIColor *)backgroundColorForEmptyDataSet:(UIScrollView *)scrollView;

自定义空白页视图

注:
1:定义视图显示而不是默认的视图,如标签,imageview和按钮。默认是nil
2:返回一个自定义视图将忽略-offsetForEmptyDataSet和-spaceHeightForEmptyDataSet配置。
- (UIView *)customViewForEmptyDataSet:(UIScrollView *)scrollView;

设置视图偏移量

注:
默认是CGPointZero:即controller视图的左上角
- (CGPoint)offsetForEmptyDataSet:(UIScrollView *)scrollView DZNEmptyDataSetDeprecated(-verticalOffsetForEmptyDataSet:);
- (CGFloat)verticalOffsetForEmptyDataSet:(UIScrollView *)scrollView;

设置空白页title、description、button等的竖直间隔

注:
1:默认是11 pts
2:该方法设置的是两两之间的间隔,所以是统一的。如果想要在视觉上设置某两控件间隔,可自定义视图
- (CGFloat)spaceHeightForEmptyDataSet:(UIScrollView *)scrollView;
Delegate:代理方法

是否要淡入

注:
1:默认是yes
2:在视觉效果上yes/no没有看到什么区别。
- (BOOL)emptyDataSetShouldFadeIn:(UIScrollView *)scrollView;

空白页是否要强制显示(重点如果您的背景视图是scrollView)

注:
1:该方法在源码中为 ‘或’ 判断条件中的后者,所以,该方法一般用在数据不为空,强制性显示空白页视图。所以,可适当的在该方法中添加判断逻辑,
2:if (([self dzn_shouldDisplay] && [self dzn_itemsCount] == 0) || [self dzn_shouldBeForcedToDisplay])。 此为源码中设置空白页的判断条件,scrollview时,items肯定为0.所以,该方法的返回值就起到了强制作用。
   如:在scrollview中,假如网络请求成功,可返回yes,如果失败返回no。
- (BOOL)emptyDataSetShouldBeForcedToDisplay:(UIScrollView *)scrollView;

设置显示空白页

注:
1:默认是yes
- (BOOL)emptyDataSetShouldDisplay:(UIScrollView *)scrollView;

是否允许触控空白页

注:
1:默认为yes
2:源码是通过该方法的返回值去设置空白页返回视图的‘用户交互’userInteractionEnabled
- (BOOL)emptyDataSetShouldAllowTouch:(UIScrollView *)scrollView;

是否允许空白页滚动

注:
1:默认是no
- (BOOL)emptyDataSetShouldAllowScroll:(UIScrollView *)scrollView;

是否允许动画运行

注:
1:默认no
2:如果不写该方法,或该方法返回值为no。那imageAnimationForEmptyDataSet设置的动画不显示
- (BOOL)emptyDataSetShouldAnimateImageView:(UIScrollView *)scrollView;

点击空白页图片事件

-(void)emptyDataSet:(UIScrollView *)scrollView didTapView:(UIView *)view

点击空白页按钮事件
注:
1:想要触发该方法,前提是设置的按钮要显示出来,所以,设置的图片不能盖着该按钮
-(void)emptyDataSet:(UIScrollView *)scrollView didTapButton:(UIButton *)button

空白页声明周期

- (void)emptyDataSetWillAppear:(UIScrollView *)scrollView;
- (void)emptyDataSetDidAppear:(UIScrollView *)scrollView;
- (void)emptyDataSetWillDisappear:(UIScrollView *)scrollView;
- (void)emptyDataSetDidDisappear:(UIScrollView *)scrollView;

二:使用

1 :接入

统一管理工具:[CocoaPods](http://cocoapods.org/?q=DZNEmptyDataSet)

或

github上下载该库
解压,将 Source中 .h  .m文件拖入工程

2 :引用

1)引入头文件
#import "UIScrollView+EmptyDataSet.h"

或

#import 
2)遵守协议

3)设置数据源、代理
self.tableView.emptyDataSetSource   = self;
self.tableView.emptyDataSetDelegate = self;

或

self.collection.emptyDataSetSource   = self;
self.collection.emptyDataSetDelegate = self;

或

self.webView.scrollView.emptyDataSetSource = self;
self.webView.scrollView.emptyDataSetDelegate = self;

或

self.scrollView.emptyDataSetSource   = self;
self.scrollView.emptyDataSetDelegate = self;
self.searchDisplayController.searchResultsTableView.emptyDataSetSource = self;
self.searchDisplayController.searchResultsTableView.emptyDataSetDelegate = self;

三:实现

1:数据源方法:

列表空白时:显示的图片
- (UIImage *)imageForEmptyDataSet:(UIScrollView *)scrollView
{
    return [UIImage imageNamed:@"empty_placeholder"];
}
可自定义的动画(平移、缩放、旋转、3D等)
- (CAAnimation *)imageAnimationForEmptyDataSet:(UIScrollView *)scrollView
{
    CABasicAnimation *animation = [CABasicAnimation         animationWithKeyPath: @"transform"];

    animation.fromValue = [NSValue                  valueWithCATransform3D:CATransform3DIdentity];
    animation.toValue = [NSValue   valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2, 0.0, 0.0, 1.0)];

    animation.duration = 0.25;
    animation.cumulative = YES;
    animation.repeatCount = MAXFLOAT;

    return animation;
}
史上最全的DZNEmptyDataSet(空白页框架)说明书_第1张图片
空白页自定义动画效果
空白页显示内容的标题
- (NSAttributedString *)titleForEmptyDataSet:(UIScrollView *)scrollView
{
NSString *text = @"这里就是显示的标题";

NSDictionary *attributes = @{NSFontAttributeName: [UIFont boldSystemFontOfSize:28.0f],
                             NSForegroundColorAttributeName: [UIColor darkGrayColor]};

return [[NSAttributedString alloc] initWithString:text attributes:attributes];
}
史上最全的DZNEmptyDataSet(空白页框架)说明书_第2张图片
空白页显示内容的标题
自定义空白页显示的视图
- (UIView *)customViewForEmptyDataSet:(UIScrollView *)scrollView
{
UIActivityIndicatorView *activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[activityView startAnimating];
return activityView;
}
史上最全的DZNEmptyDataSet(空白页框架)说明书_第3张图片
自定义视图

2:代理方法:

空白页是否显示:默认YES
- (BOOL)emptyDataSetShouldDisplay:(UIScrollView *)scrollView
{
return YES;
}
空白页是否响应交互:默认YES ..(如:点击事件)
- (BOOL)emptyDataSetShouldAllowTouch:(UIScrollView *)scrollView
{
return YES;
}
空白页是能滚动:默认NO
- (BOOL)emptyDataSetShouldAllowScroll:(UIScrollView *)scrollView
{
return YES;
}
空白页是否允许动画:默认NO
- (BOOL) emptyDataSetShouldAllowImageViewAnimate:(UIScrollView *)scrollView
{
return YES;
}
空白页上view点击事件
- (void)emptyDataSet:(UIScrollView *)scrollView didTapView:(UIView *)view
{
// Do something
}
空白页上Btn点击事件
- (void)emptyDataSet:(UIScrollView *)scrollView didTapButton:(UIButton *)button
{
// Do something
}

3:刷新:

[self.tableView reloadData];

或

[self.collectionView reloadData];

或:强制刷新 》显示空白页(scrollview)

[self.tableView reloadEmptyDataSet]

四:注意

1:针对scrollview。刷新时候没有reloadData方法。需[self.scr reloadEmptyDataSet]。

五:效果

empty.gif

拓展

1:该框架实现步骤:

1、在调用tableView.emptyDataSetSource = self 时,调用setEmptyDataSetSource方法。


2、setEmptyDataSetSource方法中,将table的reloadData方法替换为:dzn_reloadEmptyDataSet方法。


3、在table调用reloadData方法,实际调用的是dzn_reloadEmptyDataSet方法,其中调用dzn_itemsCount方法判断table是否有数据。无数据则显示无数据页面。


4、dzn_itemsCount中通过调用table view的numberOfRowsInSection方法取得当前table是否有数据。

2:要点:关联对象

1)简介
Associated Objects是Objective-C 2.0中Runtime的特性之一。最早开始使用是在OS X Snow Leopard和iOS 4中。在中定义的三个方法,也是我们深入探究Associated Objects的突破口:
2)作用
使用关联对象为已经存在的类中添加属性
3)方法
objc_setAssociatedObject
objc_getAssociatedObject
objc_removeAssociatedObjects

例:

// NSObject+AssociatedObject.h

@interface NSObject (AssociatedObject)
@property (nonatomic, strong) id associatedObject;
@end



// NSObject+AssociatedObject.m

@implementation NSObject (AssociatedObject)
@dynamic associatedObject;

- (void)setAssociatedObject:(id)object {
 objc_setAssociatedObject(self, @selector(associatedObject), object, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (id)associatedObject {
return objc_getAssociatedObject(self, @selector(associatedObject));
}

3:要点:Method Swizzling

1)简介
Method Swizzling是改变一个selector的实际实现的技术。通过这一技术,我们可以在运行时通过修改类的分发表中selector对应的函数,来修改方法的实现。
2)作用
理解为:在程序运行期间动态的给两个方法互换实现

例:(该框架源码)

// Swizzle by injecting additional implementation
Method method = class_getInstanceMethod([self class], selector);
IMP dzn_newImplementation = method_setImplementation(method, (IMP)dzn_original_implementation);

// Store the new implementation in the lookup table
NSDictionary *swizzledInfo = @{DZNSwizzleInfoOwnerKey: [self class],
                               DZNSwizzleInfoSelectorKey: NSStringFromSelector(selector),
                               DZNSwizzleInfoPointerKey: [NSValue valueWithPointer:dzn_newImplementation]};

简单写法:

//获取这个类的viewDidLoad方法,它的类型是一个objc_moethod结构体的指针
Method viewDidLoad = class_getInstanceMethod(self, @selector(viewDidLoad));

//获取自定义的方法
Method viewDidLoaded = class_getInstanceMethod(self, @selector(viewDidUnload));

//互换两个方法实现
method_exchangeImplementations(viewDidLoad, viewDidLoaded);

当在列表中调用reloadData刷新列表的时候。实际运行的方法为:dzn_original_implementation 。源码通过该方法,去根据列表的实际情况设置空白页是否显示。

参考文档

  • github库地址
  • runtime 完整总结
  • Runtime 运行时之一:类与对象

你可能感兴趣的:(史上最全的DZNEmptyDataSet(空白页框架)说明书)