-
-
Notifications
You must be signed in to change notification settings - Fork 69
/
Copy pathQueryViewModel.swift
139 lines (123 loc) · 3.87 KB
/
QueryViewModel.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//
// QueryViewModel.swift
// ParseSwift
//
// Created by Corey Baker on 7/3/21.
// Copyright © 2021 Parse Community. All rights reserved.
//
#if canImport(SwiftUI)
import Foundation
/**
A default implementation of the `QueryObservable` protocol. Suitable for `ObjectObserved`
and can be used as a SwiftUI view model.
*/
@available(macOS 10.15, iOS 13.0, macCatalyst 13.0, watchOS 6.0, tvOS 13.0, *)
open class QueryViewModel<T: ParseObject>: QueryObservable {
public var query: Query<T>
public typealias Object = T
/// Updates and notifies when the new results have been retrieved.
open var results = [Object]() {
willSet {
count = newValue.count
objectWillChange.send()
}
}
/// Updates and notifies when the count of the results have been retrieved.
open var count = 0 {
willSet {
error = nil
if newValue != results.count {
objectWillChange.send()
}
}
}
/// Updates and notifies when there is an error retrieving the results.
open var error: ParseError? {
willSet {
if newValue != nil {
results.removeAll()
count = results.count
objectWillChange.send()
}
}
}
required public init(query: Query<T>) {
self.query = query
}
open func find(options: API.Options = []) {
query.find(options: options) { result in
switch result {
case .success(let results):
self.results = results
case .failure(let error):
self.error = error
}
}
}
open func findAll(batchLimit: Int? = nil,
options: API.Options = []) {
query.findAll(batchLimit: batchLimit,
options: options) { result in
switch result {
case .success(let results):
self.results = results
case .failure(let error):
self.error = error
}
}
}
open func first(options: API.Options = []) {
query.first(options: options) { result in
switch result {
case .success(let result):
self.results = [result]
case .failure(let error):
self.error = error
}
}
}
open func count(options: API.Options = []) {
query.count(options: options) { result in
switch result {
case .success(let count):
self.count = count
case .failure(let error):
self.error = error
}
}
}
open func aggregate(_ pipeline: [[String: Encodable]],
options: API.Options = []) {
query.aggregate(pipeline, options: options) { result in
switch result {
case .success(let results):
self.results = results
case .failure(let error):
self.error = error
}
}
}
}
// MARK: QueryViewModel
@available(macOS 10.15, iOS 13.0, macCatalyst 13.0, watchOS 6.0, tvOS 13.0, *)
public extension Query {
/**
Creates a view model for this query. Suitable for `ObjectObserved`
as the view model can be used as a SwiftUI publisher. Meaning it can serve
indepedently as a ViewModel in MVVM.
*/
var viewModel: QueryViewModel<ResultType> {
QueryViewModel(query: self)
}
/**
Creates a view model for this query. Suitable for `ObjectObserved`
as the view model can be used as a SwiftUI publisher. Meaning it can serve
indepedently as a ViewModel in MVVM.
- parameter query: Any query.
- returns: The view model for this query.
*/
static func viewModel(_ query: Self) -> QueryViewModel<ResultType> {
QueryViewModel(query: query)
}
}
#endif