SwiftUIアプリでネットワーク呼び出しをトリガーして、アプリを開いたときにデータを更新するにはどうすればよいですか?

gohnjanotis

SwiftUIアプリを作成していますが、サーバーからのデータを定期的に更新する必要があります。

  • アプリを最初に開いたとき
  • アプリがフォアグラウンドに入り、過去5分間にデータが更新されていない場合

以下は私がこれまでに持っているコードです。

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)最初のポイント(アプリが最初に開かれた)について:おそらく、必要なものを取得するための最良の方法は、DataBindingObservableObjectsを使用して(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]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ