最近開始學(xué)習(xí)使用markdown來寫博客志鞍,所以拿了一個比較簡單的github項目做例子此洲。這個例子用于在頁面加載過程中出現(xiàn)的Loading汁汗、Error角寸、Empty等幾種情況。
整個一個項目主要是提供了一個協(xié)議#StatusProvider,用以統(tǒng)一解決在頁面加載過程出現(xiàn)的 加載中照卦、內(nèi)容為空、加載錯誤 這幾種情況的頁面提示。
這幾種狀態(tài)統(tǒng)一的使用一個枚舉類型來表示
public enum StatusProviderType {
case Loading
case Error(error: NSError?, retry(()-> Void)?)
case Empty(action: (()-> Void?)
case None
}
其中Loading 表示加載中拆撼,Error 表示加載出現(xiàn)錯誤闸度,Empty表示出現(xiàn)空內(nèi)容竭贩。retry和action作為閉包是外部傳入用以相應(yīng)內(nèi)容具體的點擊事件。
具體的使用方法 需要加載該view的頁面實現(xiàn)協(xié)議 StatusProvider筋岛,然后才能對應(yīng)的使用該協(xié)議內(nèi)部的顯示方法show() 和隱藏方法hide()娶视。
有兩種:默認情況以及自定義方案晒哄。
1.默認情況
show(statusType: StatusProvideType.Loading) //顯示LoadingView
show(statusType: StatusProvideType.Empty(action:{...})) //顯示空內(nèi)容的提示
show(statusType: StatusProvideType.Error(error:error,retry:{...})) //加載錯誤時的提示
2.自定義情況
這種情況睁宰,三種提示view都是自己根據(jù)需求進行定制的。
自己根據(jù)產(chǎn)品的具體需求構(gòu)造對應(yīng)的view就可以了寝凌。
源碼分析
整個源代碼主要分為4個文件柒傻,分別是StatusProvider.swift、 EmptyStatusView.swift 较木、ErrorStatusView.swift 红符、LoadingStatusView.swift四個文件。其中3個StatusView分別是源碼提供的默認頁面伐债。
StatusProvider.swift提供了最主要的協(xié)議以及相應(yīng)的方法预侯。
首先該文件定義了一個枚舉類型 StatusProviderType,分別定義了不同情況下對應(yīng)的類型以及view的相應(yīng)tag。
協(xié)議StatusOnViewProvider作為一個最基本的協(xié)議峰锁,針對不同的情況獲取需要加載的superView萎馅。
extension StatusOnViewProvider where Self : UIViewController{
public var onView: UIView {
return view
}
}
extension StatusOnViewProvider where Self: UITableViewController {
public var onView: UIView {
return view
}
}
extension StatusOnViewProvider where Self: UIView {
public var onView: UIView {
return self
}
}
其中,where起一個類型約束的作用虹蒋。確保定義的關(guān)于類型參數(shù)的需求和泛型函數(shù)或類型有關(guān)聯(lián)糜芳。
另外有兩個協(xié)議 ,用于限定empty 和error兩種情況的view。這是必須要對應(yīng)實現(xiàn)的魄衅。
public protocol EmptyStatusDisplaying: class{
var action: (()-> Void)? { set get }
}
public protocol ErrorStatusDisplaying: class{
var error: NSError? { set get }
var retry: (() -> Void)? { set get }
}
然后statusProvider 還有一個擴展峭竣,實現(xiàn)了協(xié)議內(nèi)的一些默認設(shè)定,在沒有選擇自定義view的情況下晃虫,提供默認配置皆撩。
extension StatusProvider{
public var loadingView: UIView? {
get{
#if os(tvOS)
return LoadingStatusView(loadingStyle: .Activity))
#elseif os(iOS)
return LoadingStatusView(loadingStyle: .LabelWithActivity)
#else
return nil
#endif
}
}
public var errorView: ErrorStatusDisplaying? {
get { return ErrorStatusView() }
}
public var emptyView: EmptyStatusDisplaying? {
get { return nil } } //這里下面講
public func hide(statusType type: StatusProviderType){
remove(viewTagL type.viewTag())
}
public func remove(viewTag tag:Int){
onView.viewWithTag(tag)?.removeFromSuperview()
}
public func show(statusType type: StatusProviderType){
StatusProviderType.allViewTags().forEach({remove(viewTag: $0)})
var statusView: UIView? = nil
switch type {
case let .Error(error,retry):
statusView = errorView as? UIView
(statusView as? ErrorStatusDisplaying)?.error = error
(statusView as? ErrorStatusDisplaying)?.retry = retry
case .Loading: statusView = loadingView
case let .Empty(action):
statusView = emptyView as? UIView
(statusView as? EmptyStatusDisplaying)?.action = action
case .None: break
}
statusView?.tag = type.viewTag()
addViewAndCenterConstraints(statusView) //具體view添加 詳細請看項目內(nèi)容 這里就不貼了
}
這里給出了3中情況下view的默認頁面。其中只有emptyView返回的是個view哲银,需要用戶在具體的頁面進行設(shè)定扛吞。以下給出例子:
//具體viewController 下重新定義的emptyView沮榜。
var emptyView: EmptyStatusDisplaying?{
return EmptyStatusView(title: "No Data", caption: "No data available.??", image: UIImage(named: "placeholder_instagram"), actionTitle: "Create ??")
}
這算是一種具體的實現(xiàn)形式。
hide()通過調(diào)用remove()方法將具體view 消除掉
show()方法首先將在顯示的所有狀態(tài)view清除喻粹,然后根據(jù)類型進行重新加載蟆融。
暫時先寫到這里,后續(xù)會進行補充和完善守呜。有問題可以郵件聯(lián)系我showme11211@163.com