Best-practices to download data from server in SwiftUI

送分小仙女□ 提交于 2020-12-01 07:46:48

问题


My question is a conceptual question.

I have the following code:

struct CategoriesList : View {

    @State private var categories: [CategoryMetadata] = []

    var body: some View {
        NavigationView {
            List(self.categories) { category in
                NavigationButton(destination: PostsList(category: category)) {
                    CategoryRow(category: category)
                }
            }
        }.navigationBarTitle(Text("Categorie"))
    }
}

That simply compose my UI using a list of elements (categories) and I have a state associated with my view that auto-update the view when it changes.

It's all fancy and nice but for me it's not clear WHO should fire the network request to fill the model.

I understood the bindings and the @state idea, but, in general, how should I architecture the code to have the models I need at the beginning?

In the old approach I would have implemented this behavior in the viewDidLoad, but with the new paradigm of SwiftUI, what is the best approach to get my data?


回答1:


The SwiftUI community hasn't really established any best-practices yet because the technology is so new. My answer is based off of what I've seen from different WWDC19 sessions.

First, create a BindableObject with a categories property. Then write your network request code and set self.categories to your newly downloaded categories.

import SwiftUI
import Combine

final class CategoryStore: BindableObject {
    var didChange = PassthroughSubject<Void, Never>()

    var categories = [String]()

    init() {
        // TODO: Fetch categories from API
        self.categories = ["A", "B", "C"]
    }
}

Then, add CategoryStore to View and use it with List to iterate over the categories.

import SwiftUI

struct ContentView : View {
    @ObjectBinding private var store = CategoryStore()

    var body: some View {
        List(store.categories.identified(by: \.self)) { category in
            Text(category)
        }
    }
}

Whenever the categories property updates, your UI will update with the new categories (tysm Combine)




回答2:


You could take a look at my answer here.

Basically you create a model object conforming to BindableObject :

class LoginModel : BindableObject {

    var didChange = PassthroughSubject<LoginModel, Never>()

    private(set) var username: String? {
        didSet {
            didChange.send(self)
        }
    }

    func load() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
            self.username = "Sorin"
        }
    }
}

This example simulates an async server call by using the plain ol' asyncAfter.

Then, the View links with it and it's automatically updated when the model changes.

public struct LoginScreen: View {

    @ObjectBinding var loginObject = LoginModel()

    public var body: some View {
        Group {
            if login.username == nil {
                Text("Trying to login, please wait...")
            } else {
                Text("Successful login, the username is \(loginObject.username!)")
            }
        }.onAppear {
            self.loginObject.load()
        }
    }
}

The key here is to avoid trying to make the View perform anything related to the Model, except displaying it. SwiftUI will resist you all the way :-)




回答3:


iOS developers don't seem to be as familiar to this idea as Mac OS developers, in Mac apps we split the controller layer into ViewController and ModelControllers, ViewControllers are responsible for synchronise between the views and the model, ModelControllers are responsible for managing archiving of the model etc, so SwiftUI does away with ViewControllers, but if you have network handling then thats where ModelControllers would be useful, they could handle the synchronising between you remote source and you model, this is how I am currently doing it in a sample application I am working, though I have been wondering if Combine could be used to replace that as well, that will be my next thing to experiment with.



来源:https://stackoverflow.com/questions/56690551/best-practices-to-download-data-from-server-in-swiftui

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!