作者丨大瓜
来源丨掘金
链接:
https://juejin.im/post/5e5a9b0de51d45272054bdf4
今看到GitHub推荐了个Swift的空白页展示库;本着善用轮子,提高生产力的原则,下载了源码看了下,分享给大家。
我们在使用App的时候,经常会出现因为请求不成功 / 数据错误等原因,在应用中显示一个空白页,提示用户进行操作。提示的内容包括:1.图片, 2.标题,3.提示正文,4.操作按钮。在这个库,中这些提示内容都包含在EmptyStateView
里。
EmptyStateView
这个视图定义了空白页要显示的内容以及操作。内部定义了一个ViewModel
来显示内容。EmptyStateView
遵循NibLoadable
,NibLoadable
是让实例对象从Nib中加载创建。
//视图内容
struct ViewModel {
var image: UIImage?
var title: String?
var description: String?
var titleButton: String?
}
var viewModel = ViewModel() {
didSet { fillView() }
}
//空白页格式化
var format = EmptyStateFormat() {
didSet { updateUI() }
}
//操作回调
var actionButton: ((UIButton)->())?
EmptyState
在使用这个库的时候,我们只需要设置view
的
emptyState.delegate
与emptyState.dataSource
,让代理对象遵循EmptyStateDelegate
与EmptyStateDataSource
,就可以调用show
与Hide
方法显示与隐藏空白页。
view.emptyState.delegate = self
view.emptyState.dataSource = self
那么,view
的emptyState
是怎么出现的?作者在这里使用了关联对象,动态的将EmptyState
实例关联给view
的emptyState
。
enum ViewAssociatedKeys {
static var emptyState = "emptyState"
}
public extension UIView {
var emptyState: EmptyState! {
get {
guard let saved = ao_get(pkey: &ViewAssociatedKeys.emptyState) as? EmptyState else {
self.emptyState = EmptyState(inView: self)
return self.emptyState
}
return saved
}
set { ao_set(newValue ?? EmptyState(inView: self), pkey: &ViewAssociatedKeys.emptyState) }
}
}
EmptyState
是一个类,管理空白页的显示与隐藏。在这个类的实例创建的时候,就一并创建了EmptyStateView
的实例,并且根据要显示空白页的视图(UITableView / UICollectionView)来显示,UITableView / UICollectionView里空白页都是直接设置为其背景视图。
init(inView view: UIView?) {
// 创建空白页
emptyStateView = EmptyStateView.view
emptyStateView.isHidden = true
emptyStateView.actionButton = { [weak self] (button) in
self?.didPressActionButton(button)
}
// 添加到要显示空白页的视图
if let view = view as? UITableView {
view.backgroundView = emptyStateView
tableView = view
separatorStyle = view.separatorStyle
} else if let view = view as? UICollectionView {
view.backgroundView = emptyStateView
} else {
emptyStateView.fixConstraintsInView(view)
}
}
操作的响应事件,通过EmptyStateView
的actionButton
,传递给EmptyState
的didPressActionButton()
,再传递到了EmptyStateDelegate
的emptyState()()()
,将事件的处理交由了代理对象处理。
定制化显示 - CustomState
想要空白页显示不同的图片 / 标题 / 提示语,写个Enum
,遵循CustomState
,再由对应枚举值,返回遵循CustomState
,要实现的image
/ title
/ description
/ titileButton
,返回EmptyStateFormat
的实例。EmptyStateView
的实例会根据format属性,更新显示内容。
//EmptyStateView的format属性,设置其值,会更新UI.
var format = EmptyStateFormat() {
didSet { updateUI() }
}
作者有个示例可以看下。
enum TableState: CustomState {
case noNotifications
case noBox
case noCart
case noFavorites
case noLocation
case noProfile
case noSearch
case noTags
case noInternet
case noIncome
case inviteFriend
var image: UIImage? {
switch self {
case .noNotifications: return UIImage(named: "Messages")
case .noBox: return UIImage(named: "Box")
case .noCart: return UIImage(named: "Cart")
case .noFavorites: return UIImage(named: "Favorites")
case .noLocation: return UIImage(named: "Location")
case .noProfile: return UIImage(named: "Profile")
case .noSearch: return UIImage(named: "Search")
case .noTags: return UIImage(named: "Tags")
case .noInternet: return UIImage(named: "Internet")
case .noIncome: return UIImage(named: "Income")
case .inviteFriend: return UIImage(named: "Invite")
}
}
var title: String? {
switch self {
case .noNotifications: return "No message notifications"
case .noBox: return "The box is empty"
case .noCart: return "The cart is empty"
case .noFavorites: return "No favorites"
case .noLocation: return "Where are you?"
case .noProfile: return "Not logged In"
case .noSearch: return "No results"
case .noTags: return "No collections"
case .noInternet: return "We’re Sorry"
case .noIncome: return "No income"
case .inviteFriend: return "Ask friend!"
}
}
var description: String? {
switch self {
case .noNotifications: return "Sorry, you don't have any message. Please come back later!"
case .noBox: return "You dont have any email!"
case .noCart: return "Please, select almost one item to purchase"
case .noFavorites: return "Select your favorite items first!"
case .noLocation: return "We can't find your location"
case .noProfile: return "Please register or log in first"
case .noSearch: return "Please try another search item"
case .noTags: return "Go to collect favorites products"
case .noInternet: return "Our staff is still working on the issue for better experience"
case .noIncome: return "You have no payment so contact your client"
case .inviteFriend: return "You could borrow money from your network"
}
}
var titleButton: String? {
switch self {
case .noNotifications: return "Search again?"
case .noBox: return "Search again?"
case .noCart: return "Go back"
case .noFavorites: return "Go back"
case .noLocation: return "Locate now!"
case .noProfile: return "Log in now!"
case .noSearch: return "Go back"
case .noTags: return "Go shopping"
case .noInternet: return "Try again?"
case .noIncome: return "Request payment"
case .inviteFriend: return "View contact"
}
}
}
当然也可以通过EmptyStateDataSource
返回对应状态下要显示的内容。
链接
EmptyStateKit:
https://github.com/alberdev/EmptyStateKit
近期精彩内容推荐:
在看点这里好文分享给更多人↓↓