DZNEmptyDataSet README

The project's README from github.com/dzenbot/DZNEmptyDataSet. As one markdown file: README.md.

DZNEmptyDataSet

Travis codecov Pod Version Carthage compatible License

Projects using this library

Add your project to the list here and provide a (320px wide) render of the result.

The Empty Data Set Pattern

Also known as Empty State or Blank Slate.

Most applications show lists of content (data sets), which many turn out to be empty at one point, specially for new users with blank accounts. Empty screens create confusion by not being clear about what's going on, if there is an error/bug or if the user is supposed to do something within your app to be able to consume the content.

Please read this very interesting article about Designing For The Empty States.

Screenshots_Row1 Screenshots_Row2 (These are real life examples, available in the 'Applications' sample project in the v2-Swift branch)

Empty Data Sets are helpful for:

Features

This library has been designed in a way where you won't need to extend UITableView or UICollectionView class. It will still work when using UITableViewController or UICollectionViewController. By just conforming to DZNEmptyDataSetSource & DZNEmptyDataSetDelegate, you will be able to fully customize the content and appearance of the empty states for your application.

Installation

Available in CocoaPods

pod 'DZNEmptyDataSet'

To integrate DZNEmptyDataSet into your Xcode project using Carthage, specify it in your Cartfile:

github "dzenbot/DZNEmptyDataSet"

To integrate DZNEmptyDataSet into your Xcode project using SPM, specify it in your Package.swift:

.package(
    url: "https://github.com/dzenbot/DZNEmptyDataSet",
    .branch("master")
)

For existing, go to "File Navigator" -> "Select Project" -> "Project Name" -> "Swift Packages" -> "+" -> Paste "https://github.com/dzenbot/DZNEmptyDataSet" and proceed to select your target.

How to use

For complete documentation, visit CocoaPods' auto-generated doc

Import

#import "UIScrollView+EmptyDataSet.h"

Unless you are importing as a framework, then do:

#import <DZNEmptyDataSet/UIScrollView+EmptyDataSet.h>

Protocol Conformance

Conform to datasource and/or delegate.

@interface MainViewController : UITableViewController <DZNEmptyDataSetSource, DZNEmptyDataSetDelegate>

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.tableView.emptyDataSetSource = self;
    self.tableView.emptyDataSetDelegate = self;
    
    // A little trick for removing the cell separators
    self.tableView.tableFooterView = [UIView new];
}

Data Source Implementation

Return the content you want to show on the empty state, and take advantage of NSAttributedString features to customise the text appearance.

The image for the empty state:

- (UIImage *)imageForEmptyDataSet:(UIScrollView *)scrollView
{
    return [UIImage imageNamed:@"empty_placeholder"];
}

The attributed string for the title of the empty state:

- (NSAttributedString *)titleForEmptyDataSet:(UIScrollView *)scrollView
{
    NSString *text = @"Please Allow Photo Access";
    
    NSDictionary *attributes = @{NSFontAttributeName: [UIFont boldSystemFontOfSize:18.0f],
                                 NSForegroundColorAttributeName: [UIColor darkGrayColor]};
    
    return [[NSAttributedString alloc] initWithString:text attributes:attributes];
}

The attributed string for the description of the empty state:

- (NSAttributedString *)descriptionForEmptyDataSet:(UIScrollView *)scrollView
{
    NSString *text = @"This allows you to share photos from your library and save photos to your camera roll.";
    
    NSMutableParagraphStyle *paragraph = [NSMutableParagraphStyle new];
    paragraph.lineBreakMode = NSLineBreakByWordWrapping;
    paragraph.alignment = NSTextAlignmentCenter;
    
    NSDictionary *attributes = @{NSFontAttributeName: [UIFont systemFontOfSize:14.0f],
                                 NSForegroundColorAttributeName: [UIColor lightGrayColor],
                                 NSParagraphStyleAttributeName: paragraph};
                                 
    return [[NSAttributedString alloc] initWithString:text attributes:attributes];                      
}

The attributed string to be used for the specified button state:

- (NSAttributedString *)buttonTitleForEmptyDataSet:(UIScrollView *)scrollView forState:(UIControlState)state
{
    NSDictionary *attributes = @{NSFontAttributeName: [UIFont boldSystemFontOfSize:17.0f]};

    return [[NSAttributedString alloc] initWithString:@"Continue" attributes:attributes];
}

or the image to be used for the specified button state:

- (UIImage *)buttonImageForEmptyDataSet:(UIScrollView *)scrollView forState:(UIControlState)state
{
    return [UIImage imageNamed:@"button_image"];
}

The background color for the empty state:

- (UIColor *)backgroundColorForEmptyDataSet:(UIScrollView *)scrollView
{
    return [UIColor whiteColor];
}

If you need a more complex layout, you can return a custom view instead:

- (UIView *)customViewForEmptyDataSet:(UIScrollView *)scrollView
{
    UIActivityIndicatorView *activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    [activityView startAnimating];
    return activityView;
}

The image view animation

- (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;
}

Additionally, you can also adjust the vertical alignment of the content view (ie: useful when there is tableHeaderView visible):

- (CGFloat)verticalOffsetForEmptyDataSet:(UIScrollView *)scrollView
{
    return -self.tableView.tableHeaderView.frame.size.height/2.0f;
}

Finally, you can separate components from each other (default separation is 11 pts):

- (CGFloat)spaceHeightForEmptyDataSet:(UIScrollView *)scrollView
{
    return 20.0f;
}

Delegate Implementation

Return the behaviours you would expect from the empty states, and receive the user events.

Asks to know if the empty state should be rendered and displayed (Default is YES) :

- (BOOL)emptyDataSetShouldDisplay:(UIScrollView *)scrollView
{
    return YES;
}

Asks for interaction permission (Default is YES) :

- (BOOL)emptyDataSetShouldAllowTouch:(UIScrollView *)scrollView
{
    return YES;
}

Asks for scrolling permission (Default is NO) :

- (BOOL)emptyDataSetShouldAllowScroll:(UIScrollView *)scrollView
{
    return YES;
}

Asks for image view animation permission (Default is NO) :

- (BOOL) emptyDataSetShouldAllowImageViewAnimate:(UIScrollView *)scrollView
{
    return YES;
}

Notifies when the dataset view was tapped:

- (void)emptyDataSet:(UIScrollView *)scrollView didTapView:(UIView *)view
{
    // Do something
}

Notifies when the data set call to action button was tapped:

- (void)emptyDataSet:(UIScrollView *)scrollView didTapButton:(UIButton *)button
{
    // Do something
}

Refresh layout

If you need to refresh the empty state layout, simply call:

[self.tableView reloadData];

or

[self.collectionView reloadData];

depending of which you are using.

Force layout update

You can also call [self.tableView reloadEmptyDataSet] to invalidate the current empty state layout and trigger a layout update, bypassing -reloadData. This might be useful if you have a lot of logic on your data source that you want to avoid calling, when not needed. [self.scrollView reloadEmptyDataSet] is the only way to refresh content when using with UIScrollView.

Sample projects

Applications

This project replicates several popular application's empty states (~20) with their exact content and appearance, such as Airbnb, Dropbox, Facebook, Foursquare, and many others. See how easy and flexible it is to customize the appearance of your empty states. You can also use this project as a playground to test things.

Countries

This project shows a list of the world countries loaded from CoreData. It uses NSFecthedResultController for filtering search. When searching and no content is matched, a simple empty state is shown. See how to interact between the UITableViewDataSource and the DZNEmptyDataSetSource protocols, while using a typical CoreData stack.

Colors

This project is a simple example of how this library also works with UICollectionView and UISearchDisplayController, while using Storyboards.

Collaboration

Feel free to collaborate with ideas, issues and/or pull requests.

License

(The MIT License)

Copyright (c) 2016 Ignacio Romero Zurbuchen [email protected]

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

DZNEmptyDataSet (dzenbot/DZNEmptyDataSet)

Searching Database…

12K ·GitHub
archived
这是什么东西?一个即插即用的 iOS 库,当 UITableView 和 UICollectionView 没有内容可显示时,自动展示空数据集——也叫空状态(Empty State)或空白页(Blank Slate)。
这是一个完整的 App,还是需要集成到我自己 iOS 项目里的东西?是需要集成的东西:一个即插即用的 UITableView 和 UICollectionView 分类(category)。你保留现有的 UITableViewController 或 UICollectionViewController,只要实现两个协议就能得到空状态效果。
怎么把它加到项目里并开始使用?通过 CocoaPods、Carthage 或 Swift Package Manager 安装(在 Xcode 中:File Navigator -> Swift Packages -> '+'),然后实现 DZNEmptyDataSetSource 和/或 DZNEmptyDataSetDelegate——source 负责返回要显示的内容,delegate 负责处理行为和点击。
项目里还需要别的依赖才能用吗?不需要任何第三方依赖——它是一个独立完整的 Objective-C 库,你既可以以 framework 的方式引入,也可以直接用 #import 引入。
它还在维护吗?不在了——GitHub 仓库已经归档,变成只读状态,不会再有更新。它的功能与文档描述一致,但在新项目中采用之前要权衡这一点。
它支持哪些 iOS 版本和设备?支持 iOS 6 及以上和 tvOS 9 及以上,可运行在 iPhone、iPad 和 Apple TV 上,并号称可以直接上架 App Store。
我能在商业应用里用它吗?可以——它采用 MIT 许可证发布,你可以自由使用、修改和发布,包括商业用途,只要代码中保留版权声明即可。
空状态页面能显示哪些内容?一张图片、一个标题、一段描述和一个按钮——每一项都可以通过 NSAttributedString 自定义——此外还能自定义背景颜色、间距以及垂直或水平对齐方式。对于复杂的布局,你也可以直接返回一个完全自定义的视图。
为什么非要费心做自定义空状态?因为一片空白会让用户困惑,分不清是程序出了问题还是需要他们自己操作。空状态能说明当前情况,可以在新手引导时引导用户完成第一步操作,还能避免弹出的错误提示打断用户。
除了表格视图,它还能配合其他控件用吗?可以:UICollectionView、UISearchDisplayController 和普通的 UIScrollView 也都支持,并且兼容 Storyboards。对于 UIScrollView,刷新内容的唯一方式是调用 reloadEmptyDataSet。
集成之前能先看看实际效果吗?可以。'Applications' 示例复刻了 Airbnb、Dropbox、Facebook、Foursquare 等大约 20 个热门应用的空状态;'Countries' 演示了带搜索功能的 CoreData,'Colors' 演示了配合 Storyboards 使用的集合视图。
Creator
dzenbot
Size
13.9 MB
Stars
12K
Updated
CommitFeb 02
Age
12y
Commits · 90 Days