SwiftUIアプリを作成していますが、サーバーからのデータを定期的に更新する必要があります。
以下は私がこれまでに持っているコードです。
SwiftUIアプリでアプリを初めて開いたときに、この更新コードをトリガーする最良の方法は何ですか?onAppear
アプリがフォアグラウンドに入ったときに更新をトリガーするためのグッドプラクティスにオブザーバーを追加していますか?(これはアプリの唯一のビューです)
class InfoStore {
var lastValueCheck: Date = .distantPast
}
struct ContentView : View {
var infoStore: InfoStore
private func updateValueFromServer() {
// request updated value from the server
// if the request is successful, store the new value
currentValue = 500
UserDefaults.cachedValue = 500
// hardcoded for this example
infoStore.lastValueCheck = Date()
}
private func updateValueIfOld() {
let fiveMinutesAgo: Date = Date(timeIntervalSinceNow: (-5 * 60))
if infoStore.lastValueCheck < fiveMinutesAgo {
updateValueFromServer()
}
}
@State var currentValue: Int = 100
var body: some View {
Text("\(currentValue)")
.font(.largeTitle)
.onAppear {
NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification,
object: nil,
queue: .main) { (notification) in
self.updateValueIfOld()
}
}
}
}
extension UserDefaults {
private struct Keys {
static let cachedValue = "cachedValue"
}
static var cachedValue: Int {
get {
return standard.value(forKey: Keys.cachedValue) as? Int ?? 0
}
set {
standard.set(newValue, forKey: Keys.cachedValue)
}
}
}
1)最初のポイント(アプリが最初に開かれた)について:おそらく、必要なものを取得するための最良の方法は、DataBinding
とObservableObject
sを使用して(MVVMが示唆するように)ビューの外部にロジックを抽出することです。私が何を意味するかを示すために、コードをできるだけ変更しませんでした。
import SwiftUI
class ViewModel: ObservableObject {
@Published var currentValue = -1
private var lastValueCheck = Date.distantPast
init() {
updateValueFromServer()
}
func updateValueIfOld() {
let fiveMinutesAgo: Date = Date(timeIntervalSinceNow: (-5 * 60))
if lastValueCheck < fiveMinutesAgo {
updateValueFromServer()
}
}
private func updateValueFromServer() {
// request updated value from the server
// if the request is successful, store the new value
currentValue = 500
UserDefaults.cachedValue = 500
// hardcoded for this example
lastValueCheck = Date()
}
}
struct ContentView : View {
@ObservedObject var viewModel: ViewModel
var body: some View {
Text("\(viewModel.currentValue)")
.font(.largeTitle)
.onAppear {
NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification,
object: nil,
queue: .main) { (notification) in
self.viewModel.updateValueIfOld()
}
}
}
}
extension UserDefaults {
private struct Keys {
static let cachedValue = "cachedValue"
}
static var cachedValue: Int {
get {
return standard.value(forKey: Keys.cachedValue) as? Int ?? 0
}
set {
standard.set(newValue, forKey: Keys.cachedValue)
}
}
}
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(viewModel: ViewModel())
}
}
#endif
このように、ViewModel
が作成されるとすぐにcurrentValue
が更新されます。また、currentValue
サーバー呼び出しによって変更されるたびに、UIが自動的に再作成されます。次のように変更する必要があることに注意してくださいsceneDelegate
。
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: ContentView(viewModel: ViewModel()))
self.window = window
window.makeKeyAndVisible()
}
}
2)2番目のポイントについて(アプリがフォアグラウンドに入る):オブザーバーを複数回(onAppear
が起動されるたびに)登録するため、ここでは注意が必要です。ニーズに応じて、次のことを決定する必要があります。
onDisappear
(これは非常に頻繁です)いずれにせよ、以下を実装することをお勧めします。
deinit {
}
メソッドを実行し、最終的にオブザーバーを削除します。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加