Skip to content

Commit 48a871e

Browse files
cbaker6TomWFox
andauthored
Add pull responses to Subscription for publishable VM (#71)
* Initial with tests * Add the rest of the test cases. * new cache for jazzy * Apply suggestions from code review Co-authored-by: Tom Fox <[email protected]> Co-authored-by: Tom Fox <[email protected]>
1 parent d03861f commit 48a871e

File tree

5 files changed

+878
-9
lines changed

5 files changed

+878
-9
lines changed

.github/workflows/ci.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,9 @@ jobs:
109109
uses: actions/cache@v2
110110
with:
111111
path: vendor/bundle
112-
key: ${{ runner.os }}-gem-v1-${{ hashFiles('**/Gemfile.lock') }}
112+
key: ${{ runner.os }}-gem-v2-${{ hashFiles('**/Gemfile.lock') }}
113113
restore-keys: |
114-
${{ runner.os }}-gem-v1
114+
${{ runner.os }}-gem-v2
115115
- name: Install Bundle
116116
run: |
117117
bundle config path vendor/bundle

.github/workflows/release.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ jobs:
2626
uses: actions/cache@v2
2727
with:
2828
path: vendor/bundle
29-
key: ${{ runner.os }}-gem-v1-${{ hashFiles('**/Gemfile.lock') }}
29+
key: ${{ runner.os }}-gem-v2-${{ hashFiles('**/Gemfile.lock') }}
3030
restore-keys: |
31-
${{ runner.os }}-gem-v1
31+
${{ runner.os }}-gem-v2
3232
- name: Install Bundle
3333
run: |
3434
bundle config path vendor/bundle

Sources/ParseSwift/LiveQuery/Subscription.swift

+201-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ private func == <T>(lhs: Event<T>, rhs: Event<T>) -> Bool {
6060
/**
6161
A default implementation of the `ParseSubscription` protocol. Suitable for `ObjectObserved`
6262
as the subscription can be used as a SwiftUI publisher. Meaning it can serve
63-
indepedently as a ViewModel in MVVM.
63+
indepedently as a ViewModel in MVVM. Also provides a publisher for pull responses of query such as:
64+
`find`, `first`, `count`, and `aggregate`.
6465
*/
6566
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
6667
open class Subscription<T: ParseObject>: ParseSubscription, ObservableObject {
@@ -102,6 +103,57 @@ open class Subscription<T: ParseObject>: ParseSubscription, ObservableObject {
102103
}
103104
}
104105

106+
/// The objects found in a `find`, `first`, or `aggregate`
107+
/// query.
108+
/// - note: this will only countain one item for `first`.
109+
public internal(set) var results: [T]? {
110+
willSet {
111+
if newValue != nil {
112+
resultsCodable = nil
113+
count = nil
114+
error = nil
115+
objectWillChange.send()
116+
}
117+
}
118+
}
119+
120+
/// The number of items found in a `count` query.
121+
public internal(set) var count: Int? {
122+
willSet {
123+
if newValue != nil {
124+
results = nil
125+
resultsCodable = nil
126+
error = nil
127+
objectWillChange.send()
128+
}
129+
}
130+
}
131+
132+
/// Results of a `explain` or `hint` query.
133+
public internal(set) var resultsCodable: AnyCodable? {
134+
willSet {
135+
if newValue != nil {
136+
results = nil
137+
count = nil
138+
error = nil
139+
objectWillChange.send()
140+
}
141+
}
142+
}
143+
144+
/// If an error occured during a `find`, `first`, `count`, or `aggregate`
145+
/// query.
146+
public internal(set) var error: ParseError? {
147+
willSet {
148+
if newValue != nil {
149+
count = nil
150+
results = nil
151+
resultsCodable = nil
152+
objectWillChange.send()
153+
}
154+
}
155+
}
156+
105157
/**
106158
Creates a new subscription that can be used to handle updates.
107159
*/
@@ -128,6 +180,154 @@ open class Subscription<T: ParseObject>: ParseSubscription, ObservableObject {
128180
open func didUnsubscribe() {
129181
self.unsubscribed = query
130182
}
183+
184+
/**
185+
Finds objects and publishes them as `results` afterwards.
186+
187+
- parameter options: A set of header options sent to the server. Defaults to an empty set.
188+
- parameter callbackQueue: The queue to return to after completion. Default value of `.main`.
189+
*/
190+
open func find(options: API.Options = [], callbackQueue: DispatchQueue = .main) {
191+
query.find(options: options, callbackQueue: callbackQueue) { result in
192+
switch result {
193+
194+
case .success(let results):
195+
self.results = results
196+
case .failure(let error):
197+
self.error = error
198+
}
199+
}
200+
}
201+
202+
/**
203+
Finds objects and publishes them as `resultsCodable` afterwards.
204+
205+
- parameter explain: Used to toggle the information on the query plan.
206+
- parameter hint: String or Object of index that should be used when executing query.
207+
- parameter options: A set of header options sent to the server. Defaults to an empty set.
208+
- parameter callbackQueue: The queue to return to after completion. Default value of `.main`.
209+
*/
210+
open func find(explain: Bool,
211+
hint: String? = nil,
212+
options: API.Options = [],
213+
callbackQueue: DispatchQueue = .main) {
214+
query.find(explain: explain, hint: hint, options: options, callbackQueue: callbackQueue) { result in
215+
switch result {
216+
217+
case .success(let results):
218+
self.resultsCodable = results
219+
case .failure(let error):
220+
self.error = error
221+
}
222+
}
223+
}
224+
225+
/**
226+
Gets an object and publishes them as `results` afterwards.
227+
228+
- warning: This method mutates the query. It will reset the limit to `1`.
229+
- parameter options: A set of header options sent to the server. Defaults to an empty set.
230+
- parameter callbackQueue: The queue to return to after completion. Default value of `.main`.
231+
*/
232+
open func first(options: API.Options = [], callbackQueue: DispatchQueue = .main) {
233+
query.first(options: options, callbackQueue: callbackQueue) { result in
234+
switch result {
235+
236+
case .success(let results):
237+
self.results = [results]
238+
case .failure(let error):
239+
self.error = error
240+
}
241+
}
242+
}
243+
244+
/**
245+
Gets an object and publishes them as `resultsCodable` afterwards.
246+
247+
- warning: This method mutates the query. It will reset the limit to `1`.
248+
- parameter explain: Used to toggle the information on the query plan.
249+
- parameter hint: String or Object of index that should be used when executing query.
250+
- parameter options: A set of header options sent to the server. Defaults to an empty set.
251+
- parameter callbackQueue: The queue to return to after completion. Default value of `.main`.
252+
*/
253+
open func first(explain: Bool,
254+
hint: String? = nil,
255+
options: API.Options = [],
256+
callbackQueue: DispatchQueue = .main) {
257+
query.first(explain: explain, hint: hint, options: options, callbackQueue: callbackQueue) { result in
258+
switch result {
259+
260+
case .success(let results):
261+
self.resultsCodable = results
262+
case .failure(let error):
263+
self.error = error
264+
}
265+
}
266+
}
267+
268+
/**
269+
Counts objects and publishes them as `count` afterwards.
270+
271+
- parameter options: A set of header options sent to the server. Defaults to an empty set.
272+
- parameter callbackQueue: The queue to return to after completion. Default value of `.main`.
273+
*/
274+
open func count(options: API.Options = [], callbackQueue: DispatchQueue = .main) {
275+
query.count(options: options, callbackQueue: callbackQueue) { result in
276+
switch result {
277+
278+
case .success(let results):
279+
self.count = results
280+
case .failure(let error):
281+
self.error = error
282+
}
283+
}
284+
}
285+
286+
/**
287+
Counts objects and publishes them as `resultsCodable` afterwards.
288+
289+
- parameter explain: Used to toggle the information on the query plan.
290+
- parameter hint: String or Object of index that should be used when executing query.
291+
- parameter options: A set of header options sent to the server. Defaults to an empty set.
292+
- parameter callbackQueue: The queue to return to after completion. Default value of `.main`.
293+
*/
294+
open func count(explain: Bool,
295+
hint: String? = nil,
296+
options: API.Options = [],
297+
callbackQueue: DispatchQueue = .main) {
298+
query.count(explain: explain, hint: hint, options: options) { result in
299+
switch result {
300+
301+
case .success(let results):
302+
self.resultsCodable = results
303+
case .failure(let error):
304+
self.error = error
305+
}
306+
}
307+
}
308+
309+
/**
310+
Executes an aggregate query and publishes the results as `results` afterwards.
311+
312+
- requires: `.useMasterKey` has to be available and passed as one of the set of `options`.
313+
- parameter pipeline: A pipeline of stages to process query.
314+
- parameter options: A set of header options sent to the server. Defaults to an empty set.
315+
- parameter callbackQueue: The queue to return to after completion. Default value of `.main`.
316+
- warning: This hasn't been tested thoroughly.
317+
*/
318+
open func aggregate(_ pipeline: Query<T>.AggregateType,
319+
options: API.Options = [],
320+
callbackQueue: DispatchQueue = .main) {
321+
query.aggregate(pipeline, options: options, callbackQueue: callbackQueue) { result in
322+
switch result {
323+
324+
case .success(let results):
325+
self.results = results
326+
case .failure(let error):
327+
self.error = error
328+
}
329+
}
330+
}
131331
}
132332
#endif
133333

Sources/ParseSwift/Types/Query.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -853,7 +853,7 @@ extension Query: Queryable {
853853
- parameter options: A set of header options sent to the server. Defaults to an empty set.
854854
- parameter callbackQueue: The queue to return to after completion. Default value of `.main`.
855855
- parameter completion: The block to execute.
856-
It should have the following argument signature: `(Result<[ResultType], ParseError>)`
856+
It should have the following argument signature: `(Result<[ResultType], ParseError>)`.
857857
*/
858858
public func find(options: API.Options = [], callbackQueue: DispatchQueue = .main,
859859
completion: @escaping (Result<[ResultType], ParseError>) -> Void) {
@@ -872,7 +872,7 @@ extension Query: Queryable {
872872
- parameter options: A set of header options sent to the server. Defaults to an empty set.
873873
- parameter callbackQueue: The queue to return to after completion. Default value of .main.
874874
- parameter completion: The block to execute.
875-
It should have the following argument signature: `(Result<[AnyResultType], ParseError>)`
875+
It should have the following argument signature: `(Result<[AnyResultType], ParseError>)`.
876876
*/
877877
public func find(explain: Bool, hint: String? = nil, options: API.Options = [],
878878
callbackQueue: DispatchQueue = .main,
@@ -1012,7 +1012,7 @@ extension Query: Queryable {
10121012
- parameter options: A set of header options sent to the server. Defaults to an empty set.
10131013
- parameter callbackQueue: The queue to return to after completion. Default value of `.main`.
10141014
- parameter completion: The block to execute.
1015-
It should have the following argument signature: `(Result<Int, ParseError>)`
1015+
It should have the following argument signature: `(Result<Int, ParseError>)`.
10161016
*/
10171017
public func count(explain: Bool, hint: String? = nil, options: API.Options = [],
10181018
callbackQueue: DispatchQueue = .main,
@@ -1059,7 +1059,7 @@ extension Query: Queryable {
10591059
- parameter options: A set of header options sent to the server. Defaults to an empty set.
10601060
- parameter callbackQueue: The queue to return to after completion. Default value of `.main`.
10611061
- parameter completion: The block to execute.
1062-
It should have the following argument signature: `(Result<Int, ParseError>)`
1062+
It should have the following argument signature: `(Result<[ResultType], ParseError>)`.
10631063
- warning: This hasn't been tested thoroughly.
10641064
*/
10651065
public func aggregate(_ pipeline: AggregateType,

0 commit comments

Comments
 (0)