美文网首页iOS 宝典iOS开发资料收集iOS Developer
史上最全的DZNEmptyDataSet(空白页框架)说明书

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

作者: DaZenD | 来源:发表于2017-05-18 16:04 被阅读251次

    前段时间因为有这么一个需求,就是当页面数据为空时要显示一个基础页面,引导用户进行刷新,故找到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 <DZNEmptyDataSet/UIScrollView+EmptyDataSet.h>
    
    2)遵守协议
    <DZNEmptyDataSetSource, DZNEmptyDataSetDelegate>
    
    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;
    }
    
    空白页自定义动画效果
    空白页显示内容的标题
    - (NSAttributedString *)titleForEmptyDataSet:(UIScrollView *)scrollView
    {
    NSString *text = @"这里就是显示的标题";
    
    NSDictionary *attributes = @{NSFontAttributeName: [UIFont boldSystemFontOfSize:28.0f],
                                 NSForegroundColorAttributeName: [UIColor darkGrayColor]};
    
    return [[NSAttributedString alloc] initWithString:text attributes:attributes];
    }
    
    空白页显示内容的标题
    自定义空白页显示的视图
    - (UIView *)customViewForEmptyDataSet:(UIScrollView *)scrollView
    {
    UIActivityIndicatorView *activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    [activityView startAnimating];
    return activityView;
    }
    
    自定义视图

    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中。在<objc/runtime.h>中定义的三个方法,也是我们深入探究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 。源码通过该方法,去根据列表的实际情况设置空白页是否显示。

    参考文档

    相关文章

      网友评论

      • Xavier_Lost:点赞,很全
        DaZenD:@略_0727 谢谢,比较简略,用的时候还需要自己多实践

      本文标题:史上最全的DZNEmptyDataSet(空白页框架)说明书

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