Skip to content
This repository was archived by the owner on Jun 13, 2023. It is now read-only.

Commit 5eb6f37

Browse files
authored
Fix object decoding (#76)
* Use the PFDecoder to properly decode objects instead of withoutData * Makes Bridging-header private * Include headers in Podspec * Add support for using Parse's native object encoding (#87) Create private headers to access the PFEncoder classes. Update the encoding of queries into dictionaries to properly use Parse's encoder for any PFObject subclasses.
1 parent a1bfa5e commit 5eb6f37

File tree

8 files changed

+123
-18
lines changed

8 files changed

+123
-18
lines changed

ParseLiveQuery.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Pod::Spec.new do |s|
1616
s.tvos.deployment_target = '9.0'
1717
s.osx.deployment_target = '10.10'
1818

19-
s.source_files = 'Sources/ParseLiveQuery/**/*.swift'
19+
s.source_files = 'Sources/ParseLiveQuery/**/*.{swift,h}'
2020
s.module_name = 'ParseLiveQuery'
2121

2222
s.dependency 'Parse', '~> 1.14.2'

Sources/ParseLiveQuery.xcodeproj/project.pbxproj

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,14 @@
99
/* Begin PBXBuildFile section */
1010
0632EDD41CA1A6DB00DD3CB8 /* Parse+LiveQuery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0632EDD31CA1A6DB00DD3CB8 /* Parse+LiveQuery.swift */; };
1111
0632EDD51CA1A6DB00DD3CB8 /* Parse+LiveQuery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0632EDD31CA1A6DB00DD3CB8 /* Parse+LiveQuery.swift */; };
12+
3B68E5B71DECC32300038DDD /* PFEncoder_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B68E5B61DECC32300038DDD /* PFEncoder_internal.h */; settings = {ATTRIBUTES = (Private, ); }; };
13+
3B68E5B81DECC32300038DDD /* PFEncoder_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B68E5B61DECC32300038DDD /* PFEncoder_internal.h */; settings = {ATTRIBUTES = (Private, ); }; };
1214
4A819D9D1D937866009C0F61 /* ObjCCompat.swift in Sources */ = {isa = PBXBuildFile; fileRef = F54D58B51C8E33D9009F8D6C /* ObjCCompat.swift */; };
1315
4A819D9E1D93786A009C0F61 /* ObjCCompat.swift in Sources */ = {isa = PBXBuildFile; fileRef = F54D58B51C8E33D9009F8D6C /* ObjCCompat.swift */; };
16+
4AEAE5761DAFC808005F9FFB /* PFDecoder_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AEAE5701DAFC3AF005F9FFB /* PFDecoder_internal.h */; settings = {ATTRIBUTES = (Private, ); }; };
17+
4AEAE5771DAFC808005F9FFB /* ParseLiveQuery-Bridging-Header.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AEAE5731DAFC488005F9FFB /* ParseLiveQuery-Bridging-Header.h */; settings = {ATTRIBUTES = (Private, ); }; };
18+
4AEAE5781DAFC809005F9FFB /* PFDecoder_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AEAE5701DAFC3AF005F9FFB /* PFDecoder_internal.h */; settings = {ATTRIBUTES = (Private, ); }; };
19+
4AEAE5791DAFC809005F9FFB /* ParseLiveQuery-Bridging-Header.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AEAE5731DAFC488005F9FFB /* ParseLiveQuery-Bridging-Header.h */; settings = {ATTRIBUTES = (Private, ); }; };
1420
629DC3BE90DA87A7857677D2 /* Pods_ParseLiveQuery_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE2643D85A7565FC20EE144C /* Pods_ParseLiveQuery_iOS.framework */; };
1521
DE7126BDB27E5DDB1C21490A /* Pods_ParseLiveQuery_OSX.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF5A55E51D52E372CD28FF08 /* Pods_ParseLiveQuery_OSX.framework */; };
1622
F534A5B21BDAFE0200CBD11A /* Subscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = F534A5B11BDAFE0200CBD11A /* Subscription.swift */; };
@@ -34,6 +40,9 @@
3440
/* Begin PBXFileReference section */
3541
0632EDD31CA1A6DB00DD3CB8 /* Parse+LiveQuery.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Parse+LiveQuery.swift"; sourceTree = "<group>"; };
3642
11F6DFE2732DB0DE49976BA5 /* Pods-ParseLiveQuery OSX.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ParseLiveQuery OSX.release.xcconfig"; path = "../Pods/Target Support Files/Pods-ParseLiveQuery OSX/Pods-ParseLiveQuery OSX.release.xcconfig"; sourceTree = "<group>"; };
43+
3B68E5B61DECC32300038DDD /* PFEncoder_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PFEncoder_internal.h; sourceTree = "<group>"; };
44+
4AEAE5701DAFC3AF005F9FFB /* PFDecoder_internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PFDecoder_internal.h; sourceTree = "<group>"; };
45+
4AEAE5731DAFC488005F9FFB /* ParseLiveQuery-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ParseLiveQuery-Bridging-Header.h"; sourceTree = "<group>"; };
3746
6062D7994653A4F07D1358B9 /* Pods-ParseLiveQuery iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ParseLiveQuery iOS.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-ParseLiveQuery iOS/Pods-ParseLiveQuery iOS.debug.xcconfig"; sourceTree = "<group>"; };
3847
7A40A16386D0D6B38F8B2F07 /* Pods-ParseLiveQuery-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ParseLiveQuery-iOS.release.xcconfig"; path = "../Pods/Target Support Files/Pods-ParseLiveQuery-iOS/Pods-ParseLiveQuery-iOS.release.xcconfig"; sourceTree = "<group>"; };
3948
8445DD921B87567C1E6A6042 /* Pods-ParseLiveQuery OSX.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ParseLiveQuery OSX.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-ParseLiveQuery OSX/Pods-ParseLiveQuery OSX.debug.xcconfig"; sourceTree = "<group>"; };
@@ -152,6 +161,9 @@
152161
F534A5B31BDB09CE00CBD11A /* Operation.swift */,
153162
F54D58B71C8E3446009F8D6C /* ClientPrivate.swift */,
154163
F54D58B91C8E345F009F8D6C /* BoltsHelpers.swift */,
164+
4AEAE5701DAFC3AF005F9FFB /* PFDecoder_internal.h */,
165+
3B68E5B61DECC32300038DDD /* PFEncoder_internal.h */,
166+
4AEAE5731DAFC488005F9FFB /* ParseLiveQuery-Bridging-Header.h */,
155167
);
156168
path = Internal;
157169
sourceTree = "<group>";
@@ -163,13 +175,19 @@
163175
isa = PBXHeadersBuildPhase;
164176
buildActionMask = 2147483647;
165177
files = (
178+
4AEAE5791DAFC809005F9FFB /* ParseLiveQuery-Bridging-Header.h in Headers */,
179+
4AEAE5781DAFC809005F9FFB /* PFDecoder_internal.h in Headers */,
180+
3B68E5B81DECC32300038DDD /* PFEncoder_internal.h in Headers */,
166181
);
167182
runOnlyForDeploymentPostprocessing = 0;
168183
};
169184
F5A9BFC31BE0248D00E78326 /* Headers */ = {
170185
isa = PBXHeadersBuildPhase;
171186
buildActionMask = 2147483647;
172187
files = (
188+
4AEAE5771DAFC808005F9FFB /* ParseLiveQuery-Bridging-Header.h in Headers */,
189+
4AEAE5761DAFC808005F9FFB /* PFDecoder_internal.h in Headers */,
190+
3B68E5B71DECC32300038DDD /* PFEncoder_internal.h in Headers */,
173191
);
174192
runOnlyForDeploymentPostprocessing = 0;
175193
};
@@ -460,6 +478,7 @@
460478
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
461479
MACOSX_DEPLOYMENT_TARGET = 10.10;
462480
ONLY_ACTIVE_ARCH = YES;
481+
SWIFT_OBJC_BRIDGING_HEADER = "${SWIFT_MODULE_NAME}/Internal/${SWIFT_MODULE_NAME}-Bridging-Header.h";
463482
};
464483
name = Debug;
465484
};
@@ -486,6 +505,7 @@
486505
GCC_WARN_UNUSED_VARIABLE = YES;
487506
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
488507
MACOSX_DEPLOYMENT_TARGET = 10.10;
508+
SWIFT_OBJC_BRIDGING_HEADER = "${SWIFT_MODULE_NAME}/Internal/${SWIFT_MODULE_NAME}-Bridging-Header.h";
489509
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
490510
};
491511
name = Release;

Sources/ParseLiveQuery/Internal/ClientPrivate.swift

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,18 @@ import SocketRocket
1313
import BoltsSwift
1414

1515
private func parseObject<T: PFObject>(_ objectDictionary: [String:AnyObject]) throws -> T {
16-
guard let parseClassName = objectDictionary["className"] as? String else {
16+
guard let _ = objectDictionary["className"] as? String else {
1717
throw LiveQueryErrors.InvalidJSONError(json: objectDictionary, expectedKey: "parseClassName")
1818
}
19-
guard let objectId = objectDictionary["objectId"] as? String else {
19+
guard let _ = objectDictionary["objectId"] as? String else {
2020
throw LiveQueryErrors.InvalidJSONError(json: objectDictionary, expectedKey: "objectId")
2121
}
2222

23-
let parseObject = T(withoutDataWithClassName: parseClassName, objectId: objectId)
24-
25-
// Map of strings to closures to determine if the key is valid. Allows for more advanced checking of
26-
// classnames and such.
27-
let invalidKeys: [String:(Void)->Bool] = [
28-
"objectId": { true },
29-
"parseClassName": { true },
30-
"sessionToken": { parseClassName == "_User" }
31-
]
32-
33-
objectDictionary.filter { key, _ in
34-
return !(invalidKeys[key].map { $0() } ?? false)
35-
}.forEach { key, value in
36-
parseObject[key] = value
23+
guard let object = PFDecoder.object().decode(objectDictionary) as? T else {
24+
throw LiveQueryErrors.InvalidJSONObject(json: objectDictionary, details: "cannot decode json into \(T.self)")
3725
}
38-
return parseObject
26+
27+
return object
3928
}
4029

4130
// ---------------

Sources/ParseLiveQuery/Internal/Errors.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,16 @@ public struct LiveQueryErrors {
3737
public let expectedKey: String
3838
}
3939

40+
/**
41+
An error that is reported when the server returns valid JSON, but it doesn't match the format we expect.
42+
*/
43+
public struct InvalidJSONObject: Error {
44+
/// JSON used for matching.
45+
public let json: [String:AnyObject]
46+
/// Details about the error
47+
public let details: String
48+
}
49+
4050
/**
4151
An error that is reported when the live query server encounters an internal error.
4252
*/
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//
2+
// PFDecoder_internal.h
3+
// ParseLiveQuery
4+
//
5+
// Created by Florent Vilmart on 16-10-13.
6+
// Copyright © 2016 Parse. All rights reserved.
7+
//
8+
9+
#ifndef PFDecoder_internal_h
10+
#define PFDecoder_internal_h
11+
12+
#import <Foundation/Foundation.h>
13+
14+
@interface PFDecoder: NSObject
15+
/**
16+
Globally available shared instance of PFDecoder.
17+
*/
18+
+ (nonnull PFDecoder *)objectDecoder;
19+
20+
/**
21+
Takes a complex object that was deserialized and converts encoded
22+
dictionaries into the proper Parse types. This is the inverse of
23+
encodeObject:allowUnsaved:allowObjects:seenObjects:.
24+
*/
25+
- (nullable id)decodeObject:(nullable id)object;
26+
@end
27+
28+
#endif /* PFDecoder_internal_h */
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//
2+
// PFEncoder_internal.h
3+
// ParseLiveQuery
4+
//
5+
// Created by Joe Szymanski on 11/28/16.
6+
// Copyright © 2016 Parse. All rights reserved.
7+
//
8+
9+
#ifndef PFEncoder_internal_h
10+
#define PFEncoder_internal_h
11+
12+
#import <Foundation/Foundation.h>
13+
#import <Parse/PFObject.h>
14+
15+
@interface PFEncoder : NSObject
16+
17+
+ (nonnull instancetype)objectEncoder;
18+
19+
- (nullable id)encodeObject:(nullable id)object;
20+
- (nullable id)encodeParseObject:(nullable PFObject *)object;
21+
22+
@end
23+
24+
/**
25+
Encoding strategy that rejects PFObject.
26+
*/
27+
@interface PFNoObjectEncoder : PFEncoder
28+
29+
@end
30+
31+
/**
32+
Encoding strategy that encodes PFObject to PFPointer with objectId or with localId.
33+
*/
34+
@interface PFPointerOrLocalIdObjectEncoder : PFEncoder
35+
36+
@end
37+
38+
/**
39+
Encoding strategy that encodes PFObject to PFPointer with objectId and rejects
40+
unsaved PFObject.
41+
*/
42+
@interface PFPointerObjectEncoder : PFPointerOrLocalIdObjectEncoder
43+
44+
@end
45+
46+
#endif /* PFEncoder_internal_h */
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//
2+
// ParseLiveQuery-Bridging-Header.h
3+
// ParseLiveQuery
4+
//
5+
// Created by Florent Vilmart on 16-10-13.
6+
// Copyright © 2016 Parse. All rights reserved.
7+
//
8+
9+
#import "PFDecoder_internal.h"
10+
#import "PFEncoder_internal.h"

Sources/ParseLiveQuery/Internal/QueryEncoder.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ extension Dictionary where Key: ExpressibleByStringLiteral, Value: AnyObject {
3434
encodedQueryDictionary[key] = dict.encodedQueryDictionary as? Value
3535
} else if let geoPoint = val as? PFGeoPoint {
3636
encodedQueryDictionary[key] = geoPoint.encodedDictionary as? Value
37+
} else if let object = val as? PFObject {
38+
encodedQueryDictionary[key] = PFPointerObjectEncoder.object().encode(object) as? Value
3739
} else {
3840
encodedQueryDictionary[key] = val
3941
}

0 commit comments

Comments
 (0)