Skip to content

Commit 5451e5c

Browse files
authored
feat: Add emptyObject property for sending modified keys to server (#243)
* Add emptyObject method to ParseObject * Update playground examples * Fix bug in User playground example that prevented signup due to CLP's * Nits * more nits * Turn emptyObject into computed property * nit * Fix SDK version
1 parent 087227e commit 5451e5c

File tree

33 files changed

+266
-39
lines changed

33 files changed

+266
-39
lines changed

CHANGELOG.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
11
# Parse-Swift Changelog
22

33
### main
4-
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/1.9.10...main)
4+
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/1.10.0...main)
55
* _Contributing to this repo? Add info about your change here to be included in the next release_
66

7+
### 1.10.0
8+
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/1.9.9...1.10.0)
9+
10+
__Improvements__
11+
- (Breaking Change) Provide ParseObject property, emptyObject, that makes it easy to send only modified keys to the server. This change "might" be breaking depending on your implementation as it requires ParseObjects to now have an empty initializer, init() ([#243](https://github.com/parse-community/Parse-Swift/pull/243)), thanks to [Corey Baker](https://github.com/cbaker6).
12+
713
__Fixes__
814
- ParseUser shouldn't send email if it hasn't been modified or else email verification is resent ([#241](https://github.com/parse-community/Parse-Swift/pull/241)), thanks to [Corey Baker](https://github.com/cbaker6).
915

1016
### 1.9.10
1117
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/1.9.9...1.9.10)
18+
1219
__Fixes__
1320
- ParseInstallation can't be retreived from Keychain after the first fun ([#236](https://github.com/parse-community/Parse-Swift/pull/236)), thanks to [Corey Baker](https://github.com/cbaker6).
1421

ParseSwift.playground/Pages/1 - Your first Object.xcplaygroundpage/Contents.swift

+18-5
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,12 @@ struct GameScore: ParseObject {
3939

4040
//: Your own properties.
4141
var score: Int = 0
42+
}
43+
44+
//: It's recommended to place custom initializers in an extension
45+
//: to preserve the convenience initializer.
46+
extension GameScore {
4247

43-
//: Custom initializer.
4448
init(score: Int) {
4549
self.score = score
4650
}
@@ -62,6 +66,11 @@ struct GameData: ParseObject {
6266
//: `ParseBytes` needs to be a part of the original schema
6367
//: or else you will need your masterKey to force an upgrade.
6468
var bytes: ParseBytes?
69+
}
70+
71+
//: It's recommended to place custom initializers in an extension
72+
//: to preserve the convenience initializer.
73+
extension GameData {
6574

6675
init (bytes: ParseBytes?, polygon: ParsePolygon) {
6776
self.bytes = bytes
@@ -87,9 +96,11 @@ score.save { result in
8796
assert(savedScore.score == 10)
8897

8998
/*: To modify, need to make it a var as the value type
90-
was initialized as immutable.
99+
was initialized as immutable. Using `emptyObject`
100+
allows you to only send the updated keys to the
101+
parse server as opposed to the whole object.
91102
*/
92-
var changedScore = savedScore
103+
var changedScore = savedScore.emptyObject
93104
changedScore.score = 200
94105
changedScore.save { result in
95106
switch result {
@@ -177,9 +188,11 @@ assert(savedScore?.updatedAt != nil)
177188
assert(savedScore?.score == 10)
178189

179190
/*: To modify, need to make it a var as the value type
180-
was initialized as immutable.
191+
was initialized as immutable. Using `emptyObject`
192+
allows you to only send the updated keys to the
193+
parse server as opposed to the whole object.
181194
*/
182-
guard var changedScore = savedScore else {
195+
guard var changedScore = savedScore?.emptyObject else {
183196
fatalError()
184197
}
185198
changedScore.score = 200

ParseSwift.playground/Pages/10 - Cloud Code.xcplaygroundpage/Contents.swift

+4
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,11 @@ struct GameScore: ParseObject {
9494

9595
//: Your own properties.
9696
var score: Int = 0
97+
}
9798

99+
//: It's recommended to place custom initializers in an extension
100+
//: to preserve the convenience initializer.
101+
extension GameScore {
98102
//: Custom initializer.
99103
init(score: Int) {
100104
self.score = score

ParseSwift.playground/Pages/11 - LiveQuery.xcplaygroundpage/Contents.swift

+4
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ struct GameScore: ParseObject {
2121
var score: Int = 0
2222
var location: ParseGeoPoint?
2323
var name: String?
24+
}
2425

26+
//: It's recommended to place custom initializers in an extension
27+
//: to preserve the convenience initializer.
28+
extension GameScore {
2529
//: Custom initializer.
2630
init(name: String, score: Int) {
2731
self.name = name

ParseSwift.playground/Pages/13 - Operations.xcplaygroundpage/Contents.swift

+4
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@ struct GameScore: ParseObject {
2222

2323
//: Your own properties.
2424
var score: Int = 0
25+
}
2526

27+
//: It's recommended to place custom initializers in an extension
28+
//: to preserve the convenience initializer.
29+
extension GameScore {
2630
//: Custom initializer.
2731
init(score: Int) {
2832
self.score = score

ParseSwift.playground/Pages/15 - Custom ObjectId.xcplaygroundpage/Contents.swift

+8-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,11 @@ struct GameScore: ParseObject {
3030

3131
//: Your own properties.
3232
var score: Int = 0
33+
}
3334

35+
//: It's recommended to place custom initializers in an extension
36+
//: to preserve the convenience initializer.
37+
extension GameScore {
3438
//: Custom initializer.
3539
init(objectId: String, score: Int) {
3640
self.objectId = objectId
@@ -64,9 +68,11 @@ score.save { result in
6468
print("Saved score: \(savedScore)")
6569

6670
/*: To modify, need to make it a var as the value type
67-
was initialized as immutable.
71+
was initialized as immutable. Using `emptyObject`
72+
allows you to only send the updated keys to the
73+
parse server as opposed to the whole object.
6874
*/
69-
var changedScore = savedScore
75+
var changedScore = savedScore.emptyObject
7076
changedScore.score = 200
7177
changedScore.save { result in
7278
switch result {

ParseSwift.playground/Pages/17 - SwiftUI - Finding Objects.xcplaygroundpage/Contents.swift

+4
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ struct GameScore: ParseObject, Identifiable {
3939
var location: ParseGeoPoint?
4040
var name: String?
4141
var myFiles: [ParseFile]?
42+
}
4243

44+
//: It's recommended to place custom initializers in an extension
45+
//: to preserve the convenience initializer.
46+
extension GameScore {
4347
//: Custom initializer.
4448
init(name: String, score: Int) {
4549
self.name = name

ParseSwift.playground/Pages/18 - SwiftUI - Finding Objects With Custom ViewModel.xcplaygroundpage/Contents.swift

+4
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ struct GameScore: ParseObject, Identifiable {
3939
var score: Int = 0
4040
var location: ParseGeoPoint?
4141
var name: String?
42+
}
4243

44+
//: It's recommended to place custom initializers in an extension
45+
//: to preserve the convenience initializer.
46+
extension GameScore {
4347
//: Custom initializer.
4448
init(name: String, score: Int) {
4549
self.name = name

ParseSwift.playground/Pages/19 - SwiftUI - LiveQuery.xcplaygroundpage/Contents.swift

+6-4
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ struct GameScore: ParseObject {
2929
var score: Int = 0
3030
var location: ParseGeoPoint?
3131
var name: String?
32+
}
3233

34+
//: It's recommended to place custom initializers in an extension
35+
//: to preserve the convenience initializer.
36+
extension GameScore {
3337
//: Custom initializer.
3438
init(name: String, score: Int) {
3539
self.name = name
@@ -75,9 +79,7 @@ struct ContentView: View {
7579
Text("Not subscribed to a query")
7680
}
7781

78-
Spacer()
79-
80-
Text("Update GameScore in Parse Dashboard to see changes here")
82+
Text("Update GameScore in Parse Dashboard to see changes here:")
8183

8284
Button(action: {
8385
try? query.unsubscribe()
@@ -88,8 +90,8 @@ struct ContentView: View {
8890
.foregroundColor(.white)
8991
.padding()
9092
.cornerRadius(20.0)
91-
.frame(width: 300, height: 50)
9293
})
94+
Spacer()
9395
}
9496
}
9597
}

ParseSwift.playground/Pages/4 - User - Continued.xcplaygroundpage/Contents.swift

+21-9
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@ struct User: ParseUser {
3232
var score: GameScore?
3333
var targetScore: GameScore?
3434
var allScores: [GameScore]?
35+
}
3536

37+
//: It's recommended to place custom initializers in an extension
38+
//: to preserve the convenience initializer.
39+
extension User {
3640
//: Custom init for signup.
3741
init(username: String, password: String, email: String) {
3842
self.username = username
@@ -51,7 +55,11 @@ struct GameScore: ParseObject {
5155

5256
//: Your own properties.
5357
var score: Int? = 0
58+
}
5459

60+
//: It's recommended to place custom initializers in an extension
61+
//: to preserve the convenience initializer.
62+
extension GameScore {
5563
//: Custom initializer.
5664
init(score: Int) {
5765
self.score = score
@@ -95,12 +103,15 @@ User.login(username: "hello", password: "world") { result in
95103
Asynchrounously - Performs work on background
96104
queue and returns to specified callbackQueue.
97105
If no callbackQueue is specified it returns to main queue.
106+
Using `emptyObject` allows you to only send the updated keys to the
107+
parse server as opposed to the whole object.
98108
*/
99-
User.current?.customKey = "myCustom"
100-
User.current?.score = GameScore(score: 12)
101-
User.current?.targetScore = GameScore(score: 100)
102-
User.current?.allScores = [GameScore(score: 5), GameScore(score: 8)]
103-
User.current?.save { result in
109+
var currentUser = User.current?.emptyObject
110+
currentUser?.customKey = "myCustom"
111+
currentUser?.score = GameScore(score: 12)
112+
currentUser?.targetScore = GameScore(score: 100)
113+
currentUser?.allScores = [GameScore(score: 5), GameScore(score: 8)]
114+
currentUser?.save { result in
104115

105116
switch result {
106117
case .success(let updatedUser):
@@ -145,7 +156,7 @@ do {
145156
//: you should create an instance of your user first.
146157
var newUser = User(username: "parse", password: "aPassword*", email: "[email protected]")
147158
//: Add any other additional information.
148-
newUser.targetScore = .init(score: 40)
159+
newUser.customKey = "mind"
149160
newUser.signup { result in
150161

151162
switch result {
@@ -199,9 +210,10 @@ User.anonymous.login { result in
199210
}
200211

201212
//: Convert the anonymous user to a real new user.
202-
User.current?.username = "bye"
203-
User.current?.password = "world"
204-
User.current?.signup { result in
213+
var currentUser2 = User.current?.emptyObject
214+
currentUser2?.username = "bye"
215+
currentUser2?.password = "world"
216+
currentUser2?.signup { result in
205217
switch result {
206218

207219
case .success(let user):

ParseSwift.playground/Pages/5 - ACL.xcplaygroundpage/Contents.swift

+9-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,15 @@ struct GameScore: ParseObject {
3333
//: Your own properties
3434
var score: Int
3535

36-
//: a custom initializer
36+
init() {
37+
self.score = 0
38+
}
39+
}
40+
41+
//: It's recommended to place custom initializers in an extension
42+
//: to preserve the convenience initializer.
43+
extension GameScore {
44+
//: Custom initializer.
3745
init(score: Int) {
3846
self.score = score
3947
}

ParseSwift.playground/Pages/6 - Installation.xcplaygroundpage/Contents.swift

+9-5
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,9 @@ struct Installation: ParseInstallation {
4242
designated callbackQueue. If no callbackQueue is specified it
4343
returns to main queue.
4444
*/
45-
Installation.current?.customKey = "myCustomInstallationKey2"
46-
Installation.current?.save { results in
45+
var currentInstallation = Installation.current
46+
currentInstallation?.customKey = "myCustomInstallationKey2"
47+
currentInstallation?.save { results in
4748

4849
switch results {
4950
case .success(let updatedInstallation):
@@ -56,10 +57,13 @@ Installation.current?.save { results in
5657
/*: Update your `ParseInstallation` `customKey` value.
5758
Performs work on background queue and returns to designated on
5859
designated callbackQueue. If no callbackQueue is specified it
59-
returns to main queue.
60+
returns to main queue. Using `emptyObject` allows you to only
61+
send the updated keys to the parse server as opposed to the
62+
whole object.
6063
*/
61-
Installation.current?.customKey = "updatedValue"
62-
Installation.current?.save { results in
64+
currentInstallation = currentInstallation?.emptyObject
65+
currentInstallation?.customKey = "updatedValue"
66+
currentInstallation?.save { results in
6367

6468
switch results {
6569
case .success(let updatedInstallation):

ParseSwift.playground/Pages/7 - GeoPoint.xcplaygroundpage/Contents.swift

+6-1
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,15 @@ struct GameScore: ParseObject {
2121
var updatedAt: Date?
2222
var ACL: ParseACL?
2323
var location: ParseGeoPoint?
24+
2425
//: Your own properties
2526
var score: Int?
27+
}
2628

27-
//: A custom initializer.
29+
//: It's recommended to place custom initializers in an extension
30+
//: to preserve the convenience initializer.
31+
extension GameScore {
32+
//: Custom initializer.
2833
init(score: Int) {
2934
self.score = score
3035
}

ParseSwift.playground/Pages/8 - Pointers.xcplaygroundpage/Contents.swift

+14
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ struct Book: ParseObject {
2424

2525
//: Your own properties.
2626
var title: String?
27+
}
28+
29+
//: It's recommended to place custom initializers in an extension
30+
//: to preserve the convenience initializer.
31+
extension Book {
2732

2833
init(title: String) {
2934
self.title = title
@@ -42,6 +47,15 @@ struct Author: ParseObject {
4247
var book: Book
4348
var otherBooks: [Book]?
4449

50+
init() {
51+
self.name = "hello"
52+
self.book = Book()
53+
}
54+
}
55+
56+
//: It's recommended to place custom initializers in an extension
57+
//: to preserve the convenience initializer.
58+
extension Author {
4559
init(name: String, book: Book) {
4660
self.name = name
4761
self.book = book

ParseSwift.playground/Pages/9 - Files.xcplaygroundpage/Contents.swift

+5-1
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,12 @@ struct GameScore: ParseObject {
2525
var score: Int = 0
2626
var profilePicture: ParseFile?
2727
var myData: ParseFile?
28+
}
2829

29-
//custom initializer
30+
//: It's recommended to place custom initializers in an extension
31+
//: to preserve the convenience initializer.
32+
extension GameScore {
33+
//: Custom initializer.
3034
init(score: Int) {
3135
self.score = score
3236
}

0 commit comments

Comments
 (0)