Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Post History

66%
+2 −0
Q&A Is there a correct way to fetch data with a SwiftUI ViewModel?

Background + Example Code Let's say I have a SwiftUI ViewModel like so: class ViewModel: ObservableObject { @Published var strs: [String] = [] func fetchStrs() async { // T...

0 answers  ·  posted 1y ago by MrDevel0per‭  ·  edited 1y ago by MrDevel0per‭

#3: Post edited by user avatar MrDevel0per‭ · 2023-11-11T02:07:23Z (about 1 year ago)
Clarification - this is example code above, not production code
  • # Background + Code
  • Let's say I have a SwiftUI ViewModel like so:
  • ```swift
  • class ViewModel: ObservableObject {
  • @Published var strs: [String] = []
  • func fetchStrs() async {
  • // This function would have fetching logic for whatever type the model stored
  • // Here, we are just storing some strings for simplicity.
  • // We wait one second to mimic an API Call
  • try await Task.sleep(nanoseconds: UInt64(1 * Double(NSEC_PER_SEC)))
  • self.strs = ["Hello", "World", "!"]
  • }
  • }
  • ```
  • Since the `ViewModel` would have that function to `fetchStrs` from the API, we could get this information in two ways. I could either use a `Task` and get the `String`s in the initializer like so:
  • ```swift
  • init() {
  • Task {
  • await fetchStrs()
  • }
  • }
  • ```
  • Or I could use a [`.onAppear`](https://developer.apple.com/documentation/swiftui/view/onappear(perform:)) method in my `View` ([`.task`](https://developer.apple.com/documentation/swiftui/view/task(priority:_:)) does basically the same thing with a `Task` in `onAppear`) like so:
  • ```swift
  • struct ExampleView: View {
  • @StateObject var viewModel = ViewModel()
  • var body: some View {
  • //... List of strings here
  • .task {
  • viewModel.fetchStrs()
  • }
  • }
  • }
  • ```
  • # Question
  • As seen above, I have two major ways to get dynamic data from an API at runtime. However, **which one should I use?** Are there any sort of Swift style conventions that lean toward one or the other? I recognize that `.task` or `.onAppear` may be later than expected in some cases, but that shouldn't matter because the method is asynchronous. **Is there a correct way of getting these data, or is it developer preference?**
  • # Background + Example Code
  • Let's say I have a SwiftUI ViewModel like so:
  • ```swift
  • class ViewModel: ObservableObject {
  • @Published var strs: [String] = []
  • func fetchStrs() async {
  • // This function would have fetching logic for whatever type the model stored
  • // Here, we are just storing some strings for simplicity.
  • // We wait one second to mimic an API Call
  • try await Task.sleep(nanoseconds: UInt64(1 * Double(NSEC_PER_SEC)))
  • self.strs = ["Hello", "World", "!"]
  • }
  • }
  • ```
  • Since the `ViewModel` would have that function to `fetchStrs` from the API, we could get this information in two ways. I could either use a `Task` and get the `String`s in the initializer like so:
  • ```swift
  • init() {
  • Task {
  • await fetchStrs()
  • }
  • }
  • ```
  • Or I could use a [`.onAppear`](https://developer.apple.com/documentation/swiftui/view/onappear(perform:)) method in my `View` ([`.task`](https://developer.apple.com/documentation/swiftui/view/task(priority:_:)) does basically the same thing with a `Task` in `onAppear`) like so:
  • ```swift
  • struct ExampleView: View {
  • @StateObject var viewModel = ViewModel()
  • var body: some View {
  • //... List of strings here
  • .task {
  • viewModel.fetchStrs()
  • }
  • }
  • }
  • ```
  • # Question
  • As seen above, I have two major ways to get dynamic data from an API at runtime. However, **which one should I use?** Are there any sort of Swift style conventions that lean toward one or the other? I recognize that `.task` or `.onAppear` may be later than expected in some cases, but that shouldn't matter because the method is asynchronous. **Is there a correct way of getting these data, or is it developer preference?**
#2: Post edited by user avatar MrDevel0per‭ · 2023-11-04T23:48:06Z (about 1 year ago)
Oops! Messed up the propertyWrapper.
  • # Background + Code
  • Let's say I have a SwiftUI ViewModel like so:
  • ```swift
  • class ViewModel: ObservableObject {
  • @Published var strs: [String] = []
  • func fetchStrs() async {
  • // This function would have fetching logic for whatever type the model stored
  • // Here, we are just storing some strings for simplicity.
  • // We wait one second to mimic an API Call
  • try await Task.sleep(nanoseconds: UInt64(1 * Double(NSEC_PER_SEC)))
  • self.strs = ["Hello", "World", "!"]
  • }
  • }
  • ```
  • Since the `ViewModel` would have that function to `fetchStrs` from the API, we could get this information in two ways. I could either use a `Task` and get the `String`s in the initializer like so:
  • ```swift
  • init() {
  • Task {
  • await fetchStrs()
  • }
  • }
  • ```
  • Or I could use a [`.onAppear`](https://developer.apple.com/documentation/swiftui/view/onappear(perform:)) method in my `View` ([`.task`](https://developer.apple.com/documentation/swiftui/view/task(priority:_:)) does basically the same thing with a `Task` in `onAppear`) like so:
  • ```swift
  • struct ExampleView: View {
  • @ObservableObject var viewModel = ViewModel()
  • var body: some View {
  • //... List of strings here
  • .task {
  • viewModel.fetchStrs()
  • }
  • }
  • }
  • ```
  • # Question
  • As seen above, I have two major ways to get dynamic data from an API at runtime. However, **which one should I use?** Are there any sort of Swift style conventions that lean toward one or the other? I recognize that `.task` or `.onAppear` may be later than expected in some cases, but that shouldn't matter because the method is asynchronous. **Is there a correct way of getting these data, or is it developer preference?**
  • # Background + Code
  • Let's say I have a SwiftUI ViewModel like so:
  • ```swift
  • class ViewModel: ObservableObject {
  • @Published var strs: [String] = []
  • func fetchStrs() async {
  • // This function would have fetching logic for whatever type the model stored
  • // Here, we are just storing some strings for simplicity.
  • // We wait one second to mimic an API Call
  • try await Task.sleep(nanoseconds: UInt64(1 * Double(NSEC_PER_SEC)))
  • self.strs = ["Hello", "World", "!"]
  • }
  • }
  • ```
  • Since the `ViewModel` would have that function to `fetchStrs` from the API, we could get this information in two ways. I could either use a `Task` and get the `String`s in the initializer like so:
  • ```swift
  • init() {
  • Task {
  • await fetchStrs()
  • }
  • }
  • ```
  • Or I could use a [`.onAppear`](https://developer.apple.com/documentation/swiftui/view/onappear(perform:)) method in my `View` ([`.task`](https://developer.apple.com/documentation/swiftui/view/task(priority:_:)) does basically the same thing with a `Task` in `onAppear`) like so:
  • ```swift
  • struct ExampleView: View {
  • @StateObject var viewModel = ViewModel()
  • var body: some View {
  • //... List of strings here
  • .task {
  • viewModel.fetchStrs()
  • }
  • }
  • }
  • ```
  • # Question
  • As seen above, I have two major ways to get dynamic data from an API at runtime. However, **which one should I use?** Are there any sort of Swift style conventions that lean toward one or the other? I recognize that `.task` or `.onAppear` may be later than expected in some cases, but that shouldn't matter because the method is asynchronous. **Is there a correct way of getting these data, or is it developer preference?**
#1: Initial revision by user avatar MrDevel0per‭ · 2023-11-04T23:23:29Z (about 1 year ago)
Is there a correct way to fetch data with a SwiftUI ViewModel?
# Background + Code
Let's say I have a SwiftUI ViewModel like so:
```swift
class ViewModel: ObservableObject {
    @Published var strs: [String] = []
    

    func fetchStrs() async {
    // This function would have fetching logic for whatever type the model stored
    // Here, we are just storing some strings for simplicity.
    // We wait one second to mimic an API Call
    try await Task.sleep(nanoseconds: UInt64(1 * Double(NSEC_PER_SEC)))
    self.strs = ["Hello", "World", "!"]
    }
}
```

Since the `ViewModel` would have that function to `fetchStrs` from the API, we could get this information in two ways. I could either use a `Task` and get the `String`s in the initializer like so:
```swift
init() {
    Task {
        await fetchStrs()
    }
}
```
Or I could use a [`.onAppear`](https://developer.apple.com/documentation/swiftui/view/onappear(perform:)) method in my `View` ([`.task`](https://developer.apple.com/documentation/swiftui/view/task(priority:_:)) does basically the same thing with a `Task` in `onAppear`) like so:
```swift
struct ExampleView: View {
    @ObservableObject var viewModel = ViewModel()
    var body: some View {
        //... List of strings here
        .task {
            viewModel.fetchStrs()
        }
    }
}
```

# Question
As seen above, I have two major ways to get dynamic data from an API at runtime. However, **which one should I use?** Are there any sort of Swift style conventions that lean toward one or the other? I recognize that `.task` or `.onAppear` may be later than expected in some cases, but that shouldn't matter because the method is asynchronous. **Is there a correct way of getting these data, or is it developer preference?**