美文网首页SwiftUISwiftUI
SwiftUI高手之路 View组件复用List分页Generi

SwiftUI高手之路 View组件复用List分页Generi

作者: iCloudEnd | 来源:发表于2020-01-31 22:18 被阅读0次

    SwiftUI高级之View组件复用List分页Generics

    写了80余篇SwiftUI相关的文章,总算对SwiftUI有初步了解。于是想自己是否能够也写个开源项目,让自己代码也可以复用。

    目标

    • 实现针对不同数据结构的自动分页
    • 能够自定义界面效果

    实现路径

    需要用到Swift语言的高级特性Generics(范型)。Generics可以让我们的项目变得灵活,避免重复编写相同的代码,并以清晰抽象的方式提供代码表达力。

    遇到问题

      1. 如何通过参数给范型初始化
        U.init(item: item.getShowDict())
    

    U是一个范型,通过协议实现了init,通过where明确了U是个View

      1. 协议如何用范型
    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

    1. 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)
                }
                
                
            }
        }
        
    }
    
    1. 设置协议
    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]
        }
       
    }
    
    1. 数据实例化
    // 遵守协议的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")
            ]
        }
    }
    
    1. 界面实例化
    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教程和代码关注专栏

    相关文章

      网友评论

        本文标题:SwiftUI高手之路 View组件复用List分页Generi

        本文链接:https://www.haomeiwen.com/subject/jgjnthtx.html