SwiftUI進階之View元件複用List分頁Generics
寫了80餘篇SwiftUI相關的文章,總算對SwiftUI有初步了解。于是想自己是否能夠也寫個開源項目,讓自己代碼也可以複用。
目标
- 實作針對不同資料結構的自動分頁
- 能夠自定義界面效果
實作路徑
需要用到Swift語言的進階特性Generics(範型)。Generics可以讓我們的項目變得靈活,避免重複編寫相同的代碼,并以清晰抽象的方式提供代碼表達力。
遇到問題
- 如何通過參數給範型初始化
U.init(item: item.getShowDict())
U是一個範型,通過協定實作了init,通過where明确了U是個View - 2. 協定如何用範型
protocol PageModelProtocal:Identifiable{
associatedtype T
static func row_page() ->[T]
// 擷取下一頁
var id:UUID { get set }
var name:String { get set }
func next() ->[T]
func getShowDict() ->[String:Any]
}
可以用associatedtype來解決
代碼實作
讓首頁面代碼變得簡潔
import SwiftUI
struct ContentView: View {
var body: some View {
ListPageViewG<Author,AuthorPageRow2>()
// ListPageViewG<Author,AuthorPageRow>()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
我們通過範型ListPageViewG可以自由控制顯示資料結構和效果
struct ListPageViewG<T:PageModelProtocal,U:PageRowProtocal>: View where U:View
例如設定一下基礎效果
struct ListPageViewG<T:PageModelProtocal,U:PageRowProtocal>: View where U:View
還可以設定一下複雜效果
ListPageViewG<Author,AuthorPageRow2>()
Generics制作分頁List
- List頁面
struct ListPageViewG<T:PageModelProtocal,U:PageRowProtocal>: View where U:View{
var pageMgr:PageMgrG<T> = PageMgrG<T>()
@State var items:[T] = []
@State var isLoading: Bool = false
@State var page: Int = 0
init() {
_items = State(initialValue: pageMgr.next())
}
var body: some View {
List(items){ item in
//self.pageRow
VStack{
U.init(item: item.getShowDict())
}.onAppear {
// self.myInit()
self.listItemAppears(item)
}
}
}
}
- 設定協定
protocol PageRowProtocal {
var item:[String:Any] { get set }
init(item:[String:Any])
}
protocol PageModelProtocal:Identifiable{
associatedtype T
static func row_page() ->[T]
// 擷取下一頁
var id:UUID { get set }
var name:String { get set }
func next() ->[T]
func getShowDict() ->[String:Any]
}
class PageMgrG<T:PageModelProtocal>:NSObject{
var page = 0
var pageSize = 0
func next() -> [T]{
return T.row_page() as! [T]
}
}
- 資料執行個體化
// 遵守協定的struct
struct Author:PageModelProtocal {
var id = UUID()
var name = ""
func getShowDict() ->[String:Any]{
return ["id":id,"name":name]
}
func next() -> [Self] {
return Author.row_page()
}
static func row_page() ->[Self]{
return [
Author(name:"tom"),
Author(name:"jack"),
Author(name:"mary")
]
}
}
- 界面執行個體化
import SwiftUI
struct AuthorPageRow: View ,PageRowProtocal{
var item:[String:Any]
var body: some View {
Text("(item["id"] as! UUID) (item["name"] as! String)")
}
}
struct AuthorPageRow2: View ,PageRowProtocal{
var item:[String:Any]
var body: some View {
CircleText(name: item["name"] as! String)
}
}
參考文獻
- SwiftUI 基礎之Generics 通用代碼
- SwiftUI 進階之使用generics建立一個範型struct
更多SwiftUI教程和代碼關注專欄
- 請關注我的專欄icloudend, SwiftUI教程與源碼 https://www.jianshu.com/c/7b3e3b671970