天天看點

list 分頁_SwiftUI高手之路 View元件複用List分頁Generics

SwiftUI進階之View元件複用List分頁Generics

寫了80餘篇SwiftUI相關的文章,總算對SwiftUI有初步了解。于是想自己是否能夠也寫個開源項目,讓自己代碼也可以複用。

目标

  • 實作針對不同資料結構的自動分頁
  • 能夠自定義界面效果

實作路徑

需要用到Swift語言的進階特性Generics(範型)。Generics可以讓我們的項目變得靈活,避免重複編寫相同的代碼,并以清晰抽象的方式提供代碼表達力。

遇到問題

  1. 如何通過參數給範型初始化
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
           
list 分頁_SwiftUI高手之路 View元件複用List分頁Generics

還可以設定一下複雜效果

ListPageViewG<Author,AuthorPageRow2>()
           
list 分頁_SwiftUI高手之路 View元件複用List分頁Generics

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 基礎之Generics 通用代碼
  • SwiftUI 進階之使用generics建立一個範型struct

更多SwiftUI教程和代碼關注專欄

  • 請關注我的專欄icloudend, SwiftUI教程與源碼 https://www.jianshu.com/c/7b3e3b671970

繼續閱讀