V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
0littleboy
V2EX  ›  Swift

Swift 如何优化数据加载方式?

  •  
  •   0littleboy · 2023-04-13 09:53:52 +08:00 · 879 次点击
    这是一个创建于 381 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我有一个用于记录全局数据的类

    class GlobalData {
    //    static let shared = GlobalData()
        // 不使用单例模式,没有实例,直接调用类
        static var allProblems: [Problem] = getAllProblems()
        static var allContests: [Contest] = getAllContests()
    }
    

    问题其一是使用 static 加载速度太慢了,必须等其加载完才能显示 APP 的内容

    给出其中一个调用 GlobalData 的样例

    struct HistoryContestsView: View {
        @State var contests: [Contest] = GlobalData.allContests
        @State var allProblems: [Problem] = GlobalData.allProblems
        
        var body: some View {
            NavigationView {
                // ...
            }
            .refreshable {
                reloadHistoryContests()
            }
        }
        
        private func reloadHistoryContests() {
            GlobalData.allProblems = getAllProblems()
            allProblems = GlobalData.allProblems
            GlobalData.allContests = getAllContests()
            contests = GlobalData.allContests
            print("Successfully reload history contests")
        }
    }
    

    其二是 reloadHistoryContests 内容显得十分冗余

    目前想到的策略是定义一个 ObservableObject 类 HistoryContestsView 就可以直接订阅 GlobalData 类 并且在 .task 中异步加载数据,也能解决性能问题

    class GlobalData: ObservableObject {
        @Published var allProblems: [Problem] = []
        @Published var allContests: [Contest] = []
    
        func loadData() {
            // 加载数据的代码
            // ...
            self.allProblems = getAllProblems()
            self.allContests = getAllContests()
        }
    }
    

    但又出现了个问题,在其他 model 文件中,原本调用 GlobalData.allContests 的函数,都无法使用了

    func getPredictiveContestList(by userid: String) -> [User.AttendedContest] {
            let predictiveContests = Global.allContests.filter {
                $0.avgRatingOfProblems == nil
            }
        //    print(predictiveContests)
            var res: [User.AttendedContest] = []
            for contest in predictiveContests {
                /// 参加了且有了预测结果
                // TODO - 后面统计参加了还没有结果的
                if let tmp = predictRatingOfUser(by: contest.titleSlug, userid: userid) {
                    res.append(tmp)
                }
            }
            
            return res
        }
    

    如何解决?

    gfreezy
        1
    gfreezy  
       2023-04-13 12:17:48 +08:00
    getPredictiveContestList 这个应该是个 publisher
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3670 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 10:34 · PVG 18:34 · LAX 03:34 · JFK 06:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.