Skip to content

Commit d94dcad

Browse files
authoredSep 5, 2022
feat: add set operation based on KeyPath (#403)
* wip * switch to using chainable for reverts * add file * feat: add set operation based on KeyPath * add tests and refactor general errors * add back tests for deprecated methods * add get() method * reduce codecov patch
1 parent 9dac227 commit d94dcad

23 files changed

+701
-289
lines changed
 

‎.codecov.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ coverage:
66
status:
77
patch:
88
default:
9-
target: auto
9+
target: 72
1010
changes: false
1111
project:
1212
default:

‎CHANGELOG.md

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

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

7+
### 4.10.0
8+
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/4.9.3...4.10.0)
9+
710
__New features__
11+
- Add a new operation method that allows developers to set a new value to a KeyPath without needing the string version of the key. Also adds the get() method to allow developers to get the unwrapped property of any ParseObject based on its KeyPath ([#403](https://github.com/parse-community/Parse-Swift/pull/403)), thanks to [Corey Baker](https://github.com/cbaker6).
812
- Add revertKeyPath() and revertObject() methods to ParseObject which allow developers to revert to original values of key paths or objects after mutating ParseObjects that already have an objectId ([#402](https://github.com/parse-community/Parse-Swift/pull/402)), thanks to [Corey Baker](https://github.com/cbaker6).
913

1014
### 4.9.3

‎ParseSwift.xcodeproj/project.pbxproj

+10
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,10 @@
451451
7085DDB326D1EC7F0033B977 /* ParseAuthenticationCombineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7085DDB226D1EC7F0033B977 /* ParseAuthenticationCombineTests.swift */; };
452452
7085DDB426D1EC7F0033B977 /* ParseAuthenticationCombineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7085DDB226D1EC7F0033B977 /* ParseAuthenticationCombineTests.swift */; };
453453
7085DDB526D1EC7F0033B977 /* ParseAuthenticationCombineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7085DDB226D1EC7F0033B977 /* ParseAuthenticationCombineTests.swift */; };
454+
7087A93C28C558CA00656E93 /* ParseOperation+keyPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7087A93B28C558CA00656E93 /* ParseOperation+keyPath.swift */; };
455+
7087A93D28C558CA00656E93 /* ParseOperation+keyPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7087A93B28C558CA00656E93 /* ParseOperation+keyPath.swift */; };
456+
7087A93E28C558CA00656E93 /* ParseOperation+keyPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7087A93B28C558CA00656E93 /* ParseOperation+keyPath.swift */; };
457+
7087A93F28C558CA00656E93 /* ParseOperation+keyPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7087A93B28C558CA00656E93 /* ParseOperation+keyPath.swift */; };
454458
708CADCF2872263D0066C279 /* ParseKeychainAccessGroupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 708CADCE2872263D0066C279 /* ParseKeychainAccessGroupTests.swift */; };
455459
708CADD02872263D0066C279 /* ParseKeychainAccessGroupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 708CADCE2872263D0066C279 /* ParseKeychainAccessGroupTests.swift */; };
456460
708CADD12872263D0066C279 /* ParseKeychainAccessGroupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 708CADCE2872263D0066C279 /* ParseKeychainAccessGroupTests.swift */; };
@@ -1269,6 +1273,7 @@
12691273
7085DD9326CBF3A70033B977 /* Documentation.docc */ = {isa = PBXFileReference; lastKnownFileType = folder.documentationcatalog; path = Documentation.docc; sourceTree = "<group>"; };
12701274
7085DDA226CC8A470033B977 /* ParseHealth+combine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ParseHealth+combine.swift"; sourceTree = "<group>"; };
12711275
7085DDB226D1EC7F0033B977 /* ParseAuthenticationCombineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseAuthenticationCombineTests.swift; sourceTree = "<group>"; };
1276+
7087A93B28C558CA00656E93 /* ParseOperation+keyPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ParseOperation+keyPath.swift"; sourceTree = "<group>"; };
12721277
708CADCE2872263D0066C279 /* ParseKeychainAccessGroupTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseKeychainAccessGroupTests.swift; sourceTree = "<group>"; };
12731278
708D035125215F9B00646C70 /* Deletable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Deletable.swift; sourceTree = "<group>"; };
12741279
709A147C283949D100BF85E5 /* ParseSchema.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseSchema.swift; sourceTree = "<group>"; };
@@ -2135,6 +2140,7 @@
21352140
F97B464024D9C78B00F4A88B /* ParseOperation.swift */,
21362141
703B091026BD992E005A112F /* ParseOperation+async.swift */,
21372142
7044C19E25C4FA870011F6E7 /* ParseOperation+combine.swift */,
2143+
7087A93B28C558CA00656E93 /* ParseOperation+keyPath.swift */,
21382144
91285B1B26990D7F0051B544 /* ParsePolygon.swift */,
21392145
705025BC284C610C008D6624 /* ParsePush.swift */,
21402146
705025C1284C7841008D6624 /* ParsePush+async.swift */,
@@ -2697,6 +2703,7 @@
26972703
91285B1C26990D7F0051B544 /* ParsePolygon.swift in Sources */,
26982704
91BB8FCA2690AC99005A6BA5 /* QueryViewModel.swift in Sources */,
26992705
7085DD9426CBF3A70033B977 /* Documentation.docc in Sources */,
2706+
7087A93C28C558CA00656E93 /* ParseOperation+keyPath.swift in Sources */,
27002707
705025EB285153BC008D6624 /* ParsePushApplePayloadable.swift in Sources */,
27012708
705025A928441C96008D6624 /* ParseFieldOptions.swift in Sources */,
27022709
F97B45D624D9C6F200F4A88B /* ParseEncoder.swift in Sources */,
@@ -3006,6 +3013,7 @@
30063013
91285B1D26990D7F0051B544 /* ParsePolygon.swift in Sources */,
30073014
91BB8FCB2690AC99005A6BA5 /* QueryViewModel.swift in Sources */,
30083015
7085DD9526CBF3A70033B977 /* Documentation.docc in Sources */,
3016+
7087A93D28C558CA00656E93 /* ParseOperation+keyPath.swift in Sources */,
30093017
705025EC285153BC008D6624 /* ParsePushApplePayloadable.swift in Sources */,
30103018
705025AA28441C96008D6624 /* ParseFieldOptions.swift in Sources */,
30113019
F97B45D724D9C6F200F4A88B /* ParseEncoder.swift in Sources */,
@@ -3447,6 +3455,7 @@
34473455
91679D67268E596300F71809 /* ParseVersion.swift in Sources */,
34483456
91285B1F26990D7F0051B544 /* ParsePolygon.swift in Sources */,
34493457
91BB8FCD2690AC99005A6BA5 /* QueryViewModel.swift in Sources */,
3458+
7087A93F28C558CA00656E93 /* ParseOperation+keyPath.swift in Sources */,
34503459
705025EE285153BC008D6624 /* ParsePushApplePayloadable.swift in Sources */,
34513460
705025AC28441C96008D6624 /* ParseFieldOptions.swift in Sources */,
34523461
7085DD9726CBF3A70033B977 /* Documentation.docc in Sources */,
@@ -3633,6 +3642,7 @@
36333642
91679D66268E596300F71809 /* ParseVersion.swift in Sources */,
36343643
91285B1E26990D7F0051B544 /* ParsePolygon.swift in Sources */,
36353644
91BB8FCC2690AC99005A6BA5 /* QueryViewModel.swift in Sources */,
3645+
7087A93E28C558CA00656E93 /* ParseOperation+keyPath.swift in Sources */,
36363646
705025ED285153BC008D6624 /* ParsePushApplePayloadable.swift in Sources */,
36373647
705025AB28441C96008D6624 /* ParseFieldOptions.swift in Sources */,
36383648
7085DD9626CBF3A70033B977 /* Documentation.docc in Sources */,

‎Sources/ParseSwift/Authentication/Protocols/ParseAuthentication.swift

+4-6
Original file line numberDiff line numberDiff line change
@@ -290,13 +290,11 @@ public extension ParseUser {
290290
completion(result)
291291
}
292292
} catch {
293+
let defaultError = ParseError(code: .unknownError,
294+
message: error.localizedDescription)
295+
let parseError = error as? ParseError ?? defaultError
293296
callbackQueue.async {
294-
if let parseError = error as? ParseError {
295-
completion(.failure(parseError))
296-
} else {
297-
let parseError = ParseError(code: .unknownError, message: error.localizedDescription)
298-
completion(.failure(parseError))
299-
}
297+
completion(.failure(parseError))
300298
}
301299
}
302300
}

‎Sources/ParseSwift/Documentation.docc/ParseSwift.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ To learn how to use or experiment with ParseSwift, you can run and edit the [Par
1313

1414
- ``ParseSwift/initialize(configuration:)``
1515
- ``ParseSwift/initialize(applicationId:clientKey:masterKey:serverURL:liveQueryServerURL:allowingCustomObjectIds:usingTransactions:usingEqualQueryConstraint:usingPostForQuery:keyValueStore:requestCachePolicy:cacheMemoryCapacity:cacheDiskCapacity:usingDataProtectionKeychain:deletingKeychainIfNeeded:httpAdditionalHeaders:maxConnectionAttempts:authentication:)``
16+
- ``ParseSwift/initialize(applicationId:clientKey:masterKey:serverURL:liveQueryServerURL:allowingCustomObjectIds:usingTransactions:usingEqualQueryConstraint:usingPostForQuery:keyValueStore:requestCachePolicy:cacheMemoryCapacity:cacheDiskCapacity:migratingFromObjcSDK:usingDataProtectionKeychain:deletingKeychainIfNeeded:httpAdditionalHeaders:maxConnectionAttempts:authentication:)``
1617

‎Sources/ParseSwift/Extensions/URLSession.swift

+4-5
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,10 @@ internal extension URLSession {
153153
let data = try ParseCoding.jsonEncoder().encode(location)
154154
return try .success(mapper(data))
155155
} catch {
156-
guard let parseError = error as? ParseError else {
157-
return .failure(ParseError(code: .unknownError,
158-
// swiftlint:disable:next line_length
159-
message: "Error decoding parse-server response: \(response) with error: \(String(describing: error))"))
160-
}
156+
let defaultError = ParseError(code: .unknownError,
157+
// swiftlint:disable:next line_length
158+
message: "Error decoding parse-server response: \(response) with error: \(String(describing: error))")
159+
let parseError = error as? ParseError ?? defaultError
161160
return .failure(parseError)
162161
}
163162
}

‎Sources/ParseSwift/Objects/ParseInstallation.swift

+33-38
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Foundation
1010

1111
/**
1212
Objects that conform to the `ParseInstallation` protocol have a local representation of an
13-
installation persisted to the Parse cloud. This protocol inherits from the
13+
installation persisted to the Keychain and Parse Server. This protocol inherits from the
1414
`ParseObject` protocol, and retains the same functionality of a `ParseObject`, but also extends
1515
it with installation-specific fields and related immutability and validity
1616
checks.
@@ -21,16 +21,15 @@ import Foundation
2121
is automatically updated to match the device's time zone
2222
when the `ParseInstallation` is saved, thus these fields might not reflect the
2323
latest device state if the installation has not recently been saved.
24-
2524
`ParseInstallation`s which have a valid `deviceToken` and are saved to
2625
the Parse Server can be used to target push notifications. Use `setDeviceToken` to set the
2726
`deviceToken` properly.
2827

2928
- warning: If the use of badge is desired, it should be retrieved by using UIKit, AppKit, etc. and
30-
stored in `ParseInstallation.badge` before saving/updating the installation.
31-
32-
- warning: Linux developers should set `appName`, `appIdentifier`, and `appVersion`
33-
manually as `ParseSwift` does not have access to Bundle.main.
29+
stored in `ParseInstallation.badge` when saving/updating the installation.
30+
- warning: Linux, Android, and Windows developers should set `appName`,
31+
`appIdentifier`, and `appVersion` manually as `ParseSwift` does not have access
32+
to Bundle.main.
3433
*/
3534
public protocol ParseInstallation: ParseObject {
3635

@@ -479,13 +478,12 @@ extension ParseInstallation {
479478
try Self.updateKeychainIfNeeded([foundResult])
480479
completion(.success(foundResult))
481480
} catch {
482-
let returnError: ParseError!
483-
if let parseError = error as? ParseError {
484-
returnError = parseError
485-
} else {
486-
returnError = ParseError(code: .unknownError, message: error.localizedDescription)
481+
let defaultError = ParseError(code: .unknownError,
482+
message: error.localizedDescription)
483+
let parseError = error as? ParseError ?? defaultError
484+
callbackQueue.async {
485+
completion(.failure(parseError))
487486
}
488-
completion(.failure(returnError))
489487
}
490488
} else {
491489
completion(result)
@@ -533,6 +531,7 @@ extension ParseInstallation {
533531
- returns: Returns saved `ParseInstallation`.
534532
- important: If an object saved has the same objectId as current, it will automatically update the current.
535533
*/
534+
@discardableResult
536535
public func save(options: API.Options = []) throws -> Self {
537536
try save(ignoringCustomObjectIdConfig: false,
538537
options: options)
@@ -560,6 +559,7 @@ extension ParseInstallation {
560559
- note: The default cache policy for this method is `.reloadIgnoringLocalCacheData`. If a developer
561560
desires a different policy, it should be inserted in `options`.
562561
*/
562+
@discardableResult
563563
public func save(ignoringCustomObjectIdConfig: Bool,
564564
options: API.Options = []) throws -> Self {
565565
var options = options
@@ -724,12 +724,11 @@ extension ParseInstallation {
724724
completion(result)
725725
}
726726
} catch {
727+
let defaultError = ParseError(code: .unknownError,
728+
message: error.localizedDescription)
729+
let parseError = error as? ParseError ?? defaultError
727730
callbackQueue.async {
728-
if let parseError = error as? ParseError {
729-
completion(.failure(parseError))
730-
} else {
731-
completion(.failure(.init(code: .unknownError, message: error.localizedDescription)))
732-
}
731+
completion(.failure(parseError))
733732
}
734733
}
735734
return
@@ -862,13 +861,12 @@ extension ParseInstallation {
862861
try Self.updateKeychainIfNeeded([self], deleting: true)
863862
completion(.success(()))
864863
} catch {
865-
let returnError: ParseError!
866-
if let parseError = error as? ParseError {
867-
returnError = parseError
868-
} else {
869-
returnError = ParseError(code: .unknownError, message: error.localizedDescription)
864+
let defaultError = ParseError(code: .unknownError,
865+
message: error.localizedDescription)
866+
let parseError = error as? ParseError ?? defaultError
867+
callbackQueue.async {
868+
completion(.failure(parseError))
870869
}
871-
completion(.failure(returnError))
872870
}
873871
case .failure(let error):
874872
completion(.failure(error))
@@ -937,6 +935,7 @@ public extension Sequence where Element: ParseInstallation {
937935
- note: The default cache policy for this method is `.reloadIgnoringLocalCacheData`. If a developer
938936
desires a different policy, it should be inserted in `options`.
939937
*/
938+
@discardableResult
940939
func saveAll(batchLimit limit: Int? = nil, // swiftlint:disable:this function_body_length
941940
transaction: Bool = configuration.isUsingTransactions,
942941
ignoringCustomObjectIdConfig: Bool = false,
@@ -1232,12 +1231,11 @@ public extension Sequence where Element: ParseInstallation {
12321231
commands.append(try installation.updateCommand())
12331232
}
12341233
} catch {
1234+
let defaultError = ParseError(code: .unknownError,
1235+
message: error.localizedDescription)
1236+
let parseError = error as? ParseError ?? defaultError
12351237
callbackQueue.async {
1236-
if let parseError = error as? ParseError {
1237-
completion(.failure(parseError))
1238-
} else {
1239-
completion(.failure(.init(code: .unknownError, message: error.localizedDescription)))
1240-
}
1238+
completion(.failure(parseError))
12411239
}
12421240
return
12431241
}
@@ -1275,12 +1273,11 @@ public extension Sequence where Element: ParseInstallation {
12751273
}
12761274
}
12771275
} catch {
1276+
let defaultError = ParseError(code: .unknownError,
1277+
message: error.localizedDescription)
1278+
let parseError = error as? ParseError ?? defaultError
12781279
callbackQueue.async {
1279-
if let parseError = error as? ParseError {
1280-
completion(.failure(parseError))
1281-
} else {
1282-
completion(.failure(.init(code: .unknownError, message: error.localizedDescription)))
1283-
}
1280+
completion(.failure(parseError))
12841281
}
12851282
}
12861283
}
@@ -1499,12 +1496,10 @@ public extension Sequence where Element: ParseInstallation {
14991496
}
15001497
}
15011498
} catch {
1499+
let defaultError = ParseError(code: .unknownError,
1500+
message: error.localizedDescription)
1501+
let parseError = error as? ParseError ?? defaultError
15021502
callbackQueue.async {
1503-
guard let parseError = error as? ParseError else {
1504-
completion(.failure(ParseError(code: .unknownError,
1505-
message: error.localizedDescription)))
1506-
return
1507-
}
15081503
completion(.failure(parseError))
15091504
}
15101505
}

0 commit comments

Comments
 (0)
Please sign in to comment.