SwiftUI高级之View组件复用List分页Generics
写了80余篇SwiftUI相关的文章,总算对SwiftUI有初步了解。于是想自己是否能够也写个开源项目,让自己代码也可以复用。
目标
- 实现针对不同数据结构的自动分页
- 能够自定义界面效果
实现路径
需要用到Swift语言的高级特性Generics(范型)。Generics可以让我们的项目变得灵活,避免重复编写相同的代码,并以清晰抽象的方式提供代码表达力。
遇到问题
- 如何通过参数给范型初始化
U.init(item: item.getShowDict())
U是一个范型,通过协议实现了init,通过where明确了U是个View
- 协议如何用范型
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
Jietu20200131-220511@2x.jpg
还可以设置一下复杂效果
ListPageViewG<Author,AuthorPageRow2>()
Jietu20200131-220652@2x.jpg
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教程和代码关注专栏
- 请关注我的专栏icloudend, SwiftUI教程与源码
https://www.jianshu.com/c/7b3e3b671970
网友评论