|
24 | 24 |
|
25 | 25 | #import "CQKSerializableNSObject.h" |
26 | 26 | #import "NSObject+CQKRuntime.h" |
| 27 | +#import "NSBundle+CQKBundle.h" |
27 | 28 | #import "NSDateFormatter+CQKDateFormatter.h" |
28 | 29 | #import "CQKSerializableConfiguration.h" |
29 | 30 | #import "CQKLogger.h" |
30 | 31 |
|
31 | 32 | @interface CQKSerializableNSObject () |
32 | 33 | - (void)setValueForPropertyName:(NSString *)propertyName withDictionary:(NSDictionary *)dictionary; |
33 | 34 | - (void)setValueForPropertyName:(NSString *)propertyName withArray:(NSArray *)array; |
| 35 | +- (void)setValueForPropertyName:(NSString *)propertyName withSet:(NSSet *)set; |
34 | 36 | - (void)setValueForPropertyName:(NSString *)propertyName withObject:(id)object; |
35 | 37 | @end |
36 | 38 |
|
@@ -166,44 +168,6 @@ - (void)updateWithDictionary:(NSDictionary<NSString *,__kindof NSObject *> *)dic |
166 | 168 | } |
167 | 169 | }]; |
168 | 170 |
|
169 | | -// for (NSString *propertyName in properties) { |
170 | | -// if (![self respondsToSelector:NSSelectorFromString(propertyName)]) { |
171 | | -// NSString *message = [NSString stringWithFormat:@"%s[%@] Responds to selector = NO", __PRETTY_FUNCTION__, propertyName]; |
172 | | -// [CQKLogger log:CQKLoggerLevelVerbose message:message error:nil callingClass:[self class]]; |
173 | | -// continue; |
174 | | -// } |
175 | | -// |
176 | | -// id valueObject = [self valueForKey:propertyName]; |
177 | | -// if (valueObject == nil) { |
178 | | -// NSString *message = [NSString stringWithFormat:@"%s[%@] value = nil", __PRETTY_FUNCTION__, propertyName]; |
179 | | -// [CQKLogger log:CQKLoggerLevelVerbose message:message error:nil callingClass:[self class]]; |
180 | | -// continue; |
181 | | -// } |
182 | | -// |
183 | | -// Class propertyClass = [NSObject classForPropertyName:propertyName ofClass:self.class]; |
184 | | -// NSString *serializedKey = [self serializedKeyForPropertyName:propertyName]; |
185 | | -// |
186 | | -// @try { |
187 | | -// if ([propertyClass isSubclassOfClass:[CQKSerializableNSObject class]]) { |
188 | | -// [dictionary setObject:[(CQKSerializableNSObject *)valueObject dictionary] forKey:serializedKey]; |
189 | | -// } else if ([propertyClass isSubclassOfClass:[NSArray class]]) { |
190 | | -// [dictionary setObject:[self serializedArrayForPropertyName:propertyName withArray:valueObject] forKey:serializedKey]; |
191 | | -// } else { |
192 | | -// id serializedObject = [self serializedObjectForPropertyName:propertyName withData:valueObject]; |
193 | | -// if (serializedObject != nil) { |
194 | | -// [dictionary setObject:serializedObject forKey:serializedKey]; |
195 | | -// } |
196 | | -// } |
197 | | -// } |
198 | | -// @catch (NSException *exception) { |
199 | | -// NSString *message = [NSString stringWithFormat:@"Failed to set value '%@' for key '%@': %@", valueObject, serializedKey, exception.reason]; |
200 | | -// [CQKLogger log:CQKLoggerLevelException message:message error:nil callingClass:[self class]]; |
201 | | -// } |
202 | | -// @finally { |
203 | | -// |
204 | | -// } |
205 | | -// } |
206 | | - |
207 | 171 | return dictionary; |
208 | 172 | } |
209 | 173 |
|
@@ -316,7 +280,25 @@ - (NSObject *)initializedObjectForPropertyName:(NSString *)propertyName withData |
316 | 280 | return nil; |
317 | 281 | } |
318 | 282 |
|
319 | | - if ([propertyClass isSubclassOfClass:[CQKSerializableNSObject class]]) { |
| 283 | + if ([propertyClass isSubclassOfClass:[NSArray class]]) { |
| 284 | + Class containingClass = [self objectClassOfCollectionTypeForPropertyName:propertyName]; |
| 285 | + if ([containingClass isSubclassOfClass:[NSNull class]]) { |
| 286 | + return nil; |
| 287 | + } |
| 288 | + |
| 289 | + if ([containingClass isSubclassOfClass:[CQKSerializableNSObject class]]) { |
| 290 | + return [[containingClass alloc] initWithDictionary:data]; |
| 291 | + } |
| 292 | + } else if ([propertyClass isSubclassOfClass:[NSSet class]]) { |
| 293 | + Class containingClass = [self objectClassOfCollectionTypeForPropertyName:propertyName]; |
| 294 | + if ([containingClass isSubclassOfClass:[NSNull class]]) { |
| 295 | + return nil; |
| 296 | + } |
| 297 | + |
| 298 | + if ([containingClass isSubclassOfClass:[CQKSerializableNSObject class]]) { |
| 299 | + return [[containingClass alloc] initWithDictionary:data]; |
| 300 | + } |
| 301 | + } else if ([propertyClass isSubclassOfClass:[CQKSerializableNSObject class]]) { |
320 | 302 | return [[propertyClass alloc] initWithDictionary:data]; |
321 | 303 | } else if ([propertyClass isSubclassOfClass:[NSMutableDictionary class]]) { |
322 | 304 | return [data mutableCopy]; |
@@ -351,15 +333,69 @@ - (NSObject *)serializedObjectForPropertyName:(NSString *)propertyName withData: |
351 | 333 | } |
352 | 334 | } |
353 | 335 | return serializedArray; |
354 | | - } |
355 | | - |
356 | | - if ([[data class] isSubclassOfClass:[CQKSerializableNSObject class]]) { |
| 336 | + } else if ([[data class] isSubclassOfClass:[NSSet class]]) { |
| 337 | + NSMutableSet *serializedSet = [NSMutableSet set]; |
| 338 | + for (id obj in (NSSet *)data) { |
| 339 | + if ([[obj class] isSubclassOfClass:[CQKSerializableNSObject class]]) { |
| 340 | + [serializedSet addObject:[(CQKSerializableNSObject *)obj dictionary]]; |
| 341 | + } else if ([[obj class] isSubclassOfClass:[NSObject class]]) { |
| 342 | + NSObject *serializedObject = [self serializedObjectForPropertyName:propertyName withData:obj]; |
| 343 | + if (serializedObject != nil) { |
| 344 | + [serializedSet addObject:serializedObject]; |
| 345 | + } |
| 346 | + } |
| 347 | + } |
| 348 | + return serializedSet; |
| 349 | + } else if ([[data class] isSubclassOfClass:[CQKSerializableNSObject class]]) { |
357 | 350 | return [(CQKSerializableNSObject *)data dictionary]; |
358 | 351 | } |
359 | 352 |
|
360 | 353 | return [[CQKSerializableConfiguration sharedConfiguration] serializedObjectForPropertyName:propertyName withData:data]; |
361 | 354 | } |
362 | 355 |
|
| 356 | +- (Class)objectClassOfCollectionTypeForPropertyName:(NSString *)propertyName |
| 357 | +{ |
| 358 | + if (propertyName == nil || [propertyName isEqualToString:@""]) { |
| 359 | + return [NSNull class]; |
| 360 | + } |
| 361 | + |
| 362 | + Class entityClass = NSClassFromString(propertyName); |
| 363 | + if (entityClass != nil) { |
| 364 | + return entityClass; |
| 365 | + } |
| 366 | + |
| 367 | + NSMutableString *singular = [propertyName mutableCopy]; |
| 368 | + if ([singular.lowercaseString hasSuffix:@"s"]) { |
| 369 | + [singular replaceCharactersInRange:NSMakeRange(singular.length - 1, 1) withString:@""]; |
| 370 | + } |
| 371 | + |
| 372 | + [singular replaceCharactersInRange:NSMakeRange(0, 1) withString:[singular substringToIndex:1].uppercaseString]; |
| 373 | + |
| 374 | + entityClass = NSClassFromString(singular); |
| 375 | + if (entityClass != nil) { |
| 376 | + return entityClass; |
| 377 | + } |
| 378 | + |
| 379 | + NSBundle *bundle = [NSBundle bundleForClass:self.class]; |
| 380 | + if (bundle.bundleDisplayName != nil) { |
| 381 | + NSString *moduleName = [NSString stringWithFormat:@"%@.%@", bundle.bundleDisplayName, singular]; |
| 382 | + entityClass = NSClassFromString(moduleName); |
| 383 | + if (entityClass != nil) { |
| 384 | + return entityClass; |
| 385 | + } |
| 386 | + } |
| 387 | + |
| 388 | + if (bundle.bundleName != nil) { |
| 389 | + NSString *moduleName = [NSString stringWithFormat:@"%@.%@", bundle.bundleName, singular]; |
| 390 | + entityClass = NSClassFromString(moduleName); |
| 391 | + if (entityClass != nil) { |
| 392 | + return entityClass; |
| 393 | + } |
| 394 | + } |
| 395 | + |
| 396 | + return [NSNull class]; |
| 397 | +} |
| 398 | + |
363 | 399 | #pragma mark - |
364 | 400 | - (void)setValueForPropertyName:(NSString *)propertyName withDictionary:(NSDictionary *)dictionary |
365 | 401 | { |
@@ -401,6 +437,32 @@ - (void)setValueForPropertyName:(NSString *)propertyName withArray:(NSArray *)ar |
401 | 437 | } |
402 | 438 | } |
403 | 439 |
|
| 440 | +- (void)setValueForPropertyName:(NSString *)propertyName withSet:(NSSet *)set |
| 441 | +{ |
| 442 | + if (propertyName == nil || set == nil) { |
| 443 | + return; |
| 444 | + } |
| 445 | + |
| 446 | + Class propertyClass = [NSObject classForPropertyName:propertyName ofClass:self.class]; |
| 447 | + if (propertyClass == [NSNull class]) { |
| 448 | + return; |
| 449 | + } |
| 450 | + |
| 451 | + NSMutableSet *initializedSet = [NSMutableSet set]; |
| 452 | + [set enumerateObjectsUsingBlock:^(id _Nonnull obj, BOOL * _Nonnull stop) { |
| 453 | + NSObject *initializedObject = [self initializedObjectForPropertyName:propertyName withData:obj]; |
| 454 | + if (initializedObject != nil) { |
| 455 | + [initializedSet addObject:initializedObject]; |
| 456 | + } |
| 457 | + }]; |
| 458 | + |
| 459 | + if ([propertyClass isSubclassOfClass:[NSMutableSet class]]) { |
| 460 | + [self setValue:initializedSet forKey:propertyName]; |
| 461 | + } else { |
| 462 | + [self setValue:[NSSet setWithSet:initializedSet] forKey:propertyName]; |
| 463 | + } |
| 464 | +} |
| 465 | + |
404 | 466 | - (void)setValueForPropertyName:(NSString *)propertyName withObject:(id)object |
405 | 467 | { |
406 | 468 | if (propertyName == nil || object == nil) { |
|
0 commit comments