Skip to content

Commit af0e934

Browse files
committed
Fixed some issues with boxing/unboxing ParseModel objects inside arrays and dictionaries.
1 parent 6dfd38b commit af0e934

File tree

4 files changed

+66
-13
lines changed

4 files changed

+66
-13
lines changed

ParseModel/ParseModel.m

+1-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ + (instancetype)parseModel
3434

3535
+ (void)registerParseModel
3636
{
37-
[[[ParseModelUtils sharedUtilities] registeredParseModels] setObject:[self parseModelClass]
38-
forKey:NSStringFromClass([self class])];
37+
[[ParseModelUtils sharedUtilities] registerParseModel:self];
3938
}
4039

4140
- (id)init

ParseModel/ParseModelBase.m

+2-1
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ static BOOL getPropertyInfo(Class cls,
165165
// Find the property declaration:
166166
const char *name = [propertyName UTF8String];
167167
objc_property_t property = class_getProperty(cls, name);
168+
168169
if (!property) {
169170
if (![propertyName hasPrefix: @"primitive"]) { // Ignore "primitiveXXX" KVC accessors
170171
NSLog(@"%@ has no dynamic property named '%@' -- failure likely", cls, propertyName);
@@ -178,7 +179,7 @@ static BOOL getPropertyInfo(Class cls,
178179
*declaredInClass = cls;
179180
cls = class_getSuperclass(cls);
180181
} while (class_getProperty(cls, name) == property);
181-
182+
182183
// Get the property's type:
183184
BOOL isSettable;
184185
*propertyType = getPropertyType(property, &isSettable);

ParseModel/ParseModelUtils.h

+14-4
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,29 @@
1010

1111
@interface ParseModelUtils : NSObject
1212

13+
+ (instancetype)sharedUtilities;
14+
1315
/**
16+
This is called by the Parse Models to register themselves.
17+
1418
Registered Parse Models help Parse Model know what kind of class to instantiate
15-
when doing things like unboxing array/dictionary values from the backend.
19+
when doing things like unboxing array/dictionary values from the backend.
1620
Registering your Parse Models on start-up is highly recommended. If you don't,
1721
bad things may happen.
1822
*/
19-
@property (nonatomic, strong) NSMutableDictionary *registeredParseModels;
20-
21-
+ (instancetype)sharedUtilities;
23+
- (BOOL)registerParseModel:(Class)parseModelClass;
2224

2325
// Generic boxing/unboxing methods.
2426
- (id)performBoxingIfNecessary:(id)object;
2527
- (id)performUnboxingIfNecessary:(id)object
2628
targetClass:(Class)targetClass;
2729

30+
/**
31+
Attempts to resolve the type Class this object represents in the context
32+
of this app. Usually, 'object' parameter will be of type PFObject and
33+
ParseModelUtils will use the registered Parse Models to find the right
34+
Class.
35+
*/
36+
- (Class)resolveModelClassForObject:(id)object;
37+
2838
@end

ParseModel/ParseModelUtils.m

+49-6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
#import "ParseModel.h"
1313
#import "ParseModelUser.h"
1414

15+
@interface ParseModelUtils ()
16+
@property (nonatomic, strong) NSMutableDictionary *registeredParseModels;
17+
@end
18+
1519
@implementation ParseModelUtils
1620

1721
+ (instancetype)sharedUtilities
@@ -28,6 +32,24 @@ + (instancetype)sharedUtilities
2832
return parseModelUtils;
2933
}
3034

35+
- (BOOL)registerParseModel:(Class)parseModelClass
36+
{
37+
// Get out of there cat! You are not a ParseModel.
38+
// http://getoutoftherecat.tumblr.com/
39+
if ([parseModelClass isSubclassOfClass:[ParseModel class]] == NO) {
40+
return NO;
41+
}
42+
43+
if (!self.registeredParseModels) {
44+
self.registeredParseModels = [[NSMutableDictionary alloc] init];
45+
}
46+
47+
[self.registeredParseModels setObject:NSStringFromClass(parseModelClass)
48+
forKey:[parseModelClass parseModelClass]];
49+
50+
return YES;
51+
}
52+
3153
- (id)performBoxingIfNecessary:(id)object
3254
{
3355
id boxedObject = object;
@@ -87,26 +109,47 @@ - (id)performUnboxingIfNecessary:(id)object targetClass:(Class)targetClass
87109

88110
// Let's get recursive
89111
// Handle arrays and dictionaries...
90-
else if ([targetClass isKindOfClass:[NSArray class]]) {
112+
else if ([object isKindOfClass:[NSArray class]]) {
91113
NSMutableArray *unboxedArray = [NSMutableArray array];
92114
for (id interalObject in object) {
93-
[unboxedArray addObject:[[ParseModelUtils sharedUtilities] performUnboxingIfNecessary:object targetClass:targetClass]];
115+
[unboxedArray addObject:[[ParseModelUtils sharedUtilities] performUnboxingIfNecessary:interalObject
116+
targetClass:[self resolveModelClassForObject:interalObject]]];
94117
}
95118
unboxedObject = unboxedArray;
96119
}
97-
else if ([targetClass isKindOfClass:[NSDictionary class]]) {
120+
else if ([object isKindOfClass:[NSDictionary class]]) {
98121
NSMutableDictionary *unboxedDictionary = [NSMutableDictionary dictionary];
99122
NSArray *keys = [object allKeys];
100123
for (id key in keys) {
101-
id unboxedKey = [[ParseModelUtils sharedUtilities] performUnboxingIfNecessary:key targetClass:[key class]];
102-
id unboxedValue = [[ParseModelUtils sharedUtilities] performUnboxingIfNecessary:[object objectForKey:key]
103-
targetClass:[[object objectForKey:key] class]];
124+
id unboxedKey = [[ParseModelUtils sharedUtilities] performUnboxingIfNecessary:key targetClass:[self resolveModelClassForObject:key]];
125+
id rawValue = [object objectForKey:key];
126+
id unboxedValue = [[ParseModelUtils sharedUtilities] performUnboxingIfNecessary:rawValue
127+
targetClass:[self resolveModelClassForObject:rawValue]];
104128
[unboxedDictionary setObject:unboxedValue forKey:unboxedKey];
105129
}
106130
unboxedObject = unboxedDictionary;
107131
}
108132

133+
// Lastly, if this class is a PFObject and it is registered, instantiate the appropriate ParseModel...
134+
else if ([object isKindOfClass:[PFObject class]]) {
135+
NSString *unboxedClassString = [self.registeredParseModels objectForKey:[(PFObject *)object parseClassName]];
136+
if (unboxedClassString.length) {
137+
unboxedObject = [[NSClassFromString(unboxedClassString) alloc] initWithParseObject:object];
138+
}
139+
}
140+
109141
return unboxedObject;
110142
}
111143

144+
- (Class)resolveModelClassForObject:(id)object
145+
{
146+
if ([object isKindOfClass:[PFObject class]]) {
147+
NSString *classString = [self.registeredParseModels objectForKey:[(PFObject *)object parseClassName]];
148+
return NSClassFromString(classString);
149+
}
150+
else {
151+
return [object class];
152+
}
153+
}
154+
112155
@end

0 commit comments

Comments
 (0)