仅在冷启动或设置更改时重新加载表数据

Posted

技术标签:

【中文标题】仅在冷启动或设置更改时重新加载表数据【英文标题】:Reload table data only if cold launch or settings change 【发布时间】:2022-01-21 19:02:25 【问题描述】:

我有一个简单的两个选项卡式应用程序,我正在尝试管理 List 何时或是否从网络重新加载数据。

我希望应用仅在以下情况下重新加载数据:

首次冷启动(关闭状态启动); 从.background.active 状态;或 切换SettingsView() 中的设置

我不希望 List 在不切换选项或一般只切换标签的情况下转到 SettingsView() 时重新加载。

// tab view
struct Tabs: View 
 var body: some View 
  TabView 
   ViewOne().tabItem  Label("Settings", systemImage: "gear") 
   ViewTwo().tabItem  Label("List", systemImage: "bag") 
  
 


// ViewOne
struct ViewOne: View 
 var body: some View 
  Text("View one: Settings")
  // toggles and options here
   .onChange(of: option)  value in
    // do other things here
    UserDefaults.standard.set(true, forKey: "reloadList")
   
 


// ViewTwo
struct ViewTwo: View 
 var body: some View 
 List(arrayItems)  item in
 
  .onAppear 
   if( UserDefaults.standard.bool(forKey: "reloadList") ) 
    reloadData()
    UserDefaults.standard.removeObject(forKey: "reloadList")
   
  
 

以上在运行应用程序时有效,我切换设置 - UserDefaults 触发 reloadData() 函数。这也解决了我切换标签(无需设置更改)和不重新加载数据的困境。

但是,由于该表在启动时(冷态或背景)无法获取数据,因此我现在用糟糕的 UX 将自己击中了脚。

我尝试将另一个UserDefaults.standard.set(true, "coldLaunch") 添加到Tabs 视图,然后将reloadList 设置为true,但直到切换标签然后再返回时才会触发。

我也尝试过从@Environment(\.scenePhase) var scenePhase 设置或触发reloadData(),但这会在每次启动时触发onAppear

也许我没有直接思考,但我试图找出正确的流程效果但不能!

【问题讨论】:

【参考方案1】:

我最终尽可能地解决了这个问题,并认为我会在这里为其他可能想在他们的应用中找到解决方法的用户提供它。

在 TabView 中:

struct Tabs: View 
 @Environment(\.scenePhase) private var scenePhase
 var body: some View 
  TabView 
   ViewOne().tabItem  Label("Settings", systemImage: "gear") 
   ViewTwo().tabItem  Label("List", systemImage: "bag") 
  

  // -- when the view is active reload the table
  .onChange(of: scenePhase)  phase in
   if( phase == .active ) 
    reloadData()
   
  

 

然后在另一个要重新加载的视图上添加.onAppear 代码:

.onAppear 
 if( UserDefaults.standard.bool(forKey: "reloadList") ) 
  reloadData()
  UserDefaults.standard.removeObject(forKey: "reloadList")
 

其中UserDefaults.standard.bool(forKey: "reloadList") 设置为true 从另一个视图的更改。

有一些问题基于应用何时变为inactive,但由于ios的结构方式,没有任何方法可以隔离inactive而不访问active / background状态。

【讨论】:

【参考方案2】:
1. cold booting first time (closed state to launch);
2. going from .background to .active state; or
3. toggling a setting in the SettingsView()

对于冷启动: 您可以尝试使用这个https://developer.apple.com/documentation/uikit/uiapplication/1622944-willenterforegroundnotification,或者甚至可能只是将reload() 放在viewDidLoad() 中,因为这是在应用程序第一次启动时调用的。

 NotificationCenter.default.addObserver(self, selector:#selector(appToForeground), name: UIApplication.willEnterForegroundNotification, object: nil)

@objc func appToForeground(_ notification: Notification) 
    print("appToForeground ")


为了在 SettingsView() 中切换设置,我也在使用通知中心。类似的东西

在您的第一个标签的viewDidLoad() 中,您设置了一个观察者

NotificationCenter.default.addObserver(self,
                                       selector: #selector(self.refreshTable),
                                       name: NSNotification.Name(rawValue: "newDataNotif"),
                                       object: nil)

 

    @objc func refreshTable() 
      reloadData()
      self.tableView.reloadData()
    

然后在您的第二个选项卡上,当您的设置发生更改并且您想在第一个选项卡中重新加载表格时,这就是您所做的。

例如:

  user.setting.changed = true
  NotificationCenter.default.post(name: NSNotification.Name(rawValue: "newDataNotif"), object: nil)

一旦您的设置发生更改,此通知将发布,然后您放置在第一个选项卡中的observer 将接收通知,然后它会调用@objc func refreshTable() 然后你的表就会刷新。

【讨论】:

以上是关于仅在冷启动或设置更改时重新加载表数据的主要内容,如果未能解决你的问题,请参考以下文章

微信小程序如何升级最新版本

Android高手笔记 - 启动优化

微信小程序启动更新机制

【unity】第一次启动项目冷启动优化

表数据不会动态重新加载

热启动与冷启动