Created
July 23, 2010 03:12
-
-
Save jimkang/486951 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// OGKeyPath.h | |
// | |
// Created by Jim on 3/11/10. | |
// | |
// Copyright (c) 2010 Jim Kang/Phalange Software. | |
// | |
// Permission is hereby granted, free of charge, to any person | |
// obtaining a copy of this software and associated documentation | |
// files (the "Software"), to deal in the Software without | |
// restriction, including without limitation the rights to use, | |
// copy, modify, merge, publish, distribute, sublicense, and/or sell | |
// copies of the Software, and to permit persons to whom the | |
// Software is furnished to do so, subject to the following | |
// conditions: | |
// | |
// The above copyright notice and this permission notice shall be | |
// included in all copies or substantial portions of the Software. | |
// | |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | |
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
// OTHER DEALINGS IN THE SOFTWARE. | |
#import <Foundation/Foundation.h> | |
@interface OGKeyPath : NSObject | |
{ | |
} | |
// Cocoa KVC key paths let you get at elements with an object hierarchy, provided | |
// everything in your desired path is KVC-compliant. Unfortunately, NSArray | |
// elements cannot be referenced in key path strings. | |
// OGKeyPath provides a way to traverse those hierarchies containing arrays. | |
// "Extended key path" arguments for OGKeyPath methods are like KVC key paths but are | |
// arrays instead of strings. A key path segment may be a NSNumber representing an index | |
// in an NSArray or an NSString representing a property of an object. | |
// | |
// e.g. This extended key path | |
// | |
// [@"configs", [NSNumber numberWithInt:3], @"color", @"alpha"] | |
// | |
// would map to the value 0.5 on the hierarchy in the diagram below, which has "foo" at | |
// the top level: | |
// | |
// foo | |
// { | |
// users: { ... }, | |
// something: "whatever", | |
// configs: | |
// [ | |
// config1: { ... }, | |
// config2: { ... }, | |
// config3: { ... }, | |
// config4: | |
// { | |
// size: 50, | |
// color: | |
// { | |
// r: 0, | |
// g: 255, | |
// b: 255, | |
// alpha: 0.5 (*) | |
// } | |
// } | |
// ] | |
//} | |
// Example: | |
// [OGKeyPath set:myObject value:[NSNumber numberWithFloat:1.0f] forExtendedKeyPath: | |
// [NSArray arrayWithObjects:@"configs", [NSNumber numberWithInt:3], @"color", @"alpha", nil]]; | |
+ (void)set:(id)kvcObject value:(id)value forExtendedKeyPath:(NSArray *)path; | |
// Alternate version that puts the array together for you. | |
// Example: | |
// [OGKeyPath set:myObject value:[NSNumber numberWithFloat:1.0f] forExtendedKeyPathWithObjects: | |
// @"configs", [NSNumber numberWithInt:3], @"color", @"alpha", nil]; | |
+ (void)set:(id)kvcObject value:(id)value forExtendedKeyPathWithObjects:(id)firstPathSegment, ...; | |
// Example: | |
// [OGKeyPath valueFrom:myObject forExtendedKeyPath: | |
// [NSArray arrayWithObjects:@"configs", [NSNumber numberWithInt:3], @"color", @"alpha", nil]]; | |
+ (id)valueFrom:(id)kvcObject forExtendedKeyPath:(NSArray *)path; | |
// Alternate version that puts the array together for you. | |
// Example: | |
// [OGKeyPath valueFrom:myObject forExtendedKeyPathWithObjects: | |
// @"configs", [NSNumber numberWithInt:3], @"color", @"alpha", nil]; | |
+ (id)valueFrom:(id)kvcObject forExtendedKeyPathWithObjects:(id)firstPathSegment, ...; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// OGKeyPath.m | |
// | |
// Created by Jim on 3/11/10. | |
// | |
// Copyright (c) 2010 Jim Kang/Phalange Software. | |
// | |
// Permission is hereby granted, free of charge, to any person | |
// obtaining a copy of this software and associated documentation | |
// files (the "Software"), to deal in the Software without | |
// restriction, including without limitation the rights to use, | |
// copy, modify, merge, publish, distribute, sublicense, and/or sell | |
// copies of the Software, and to permit persons to whom the | |
// Software is furnished to do so, subject to the following | |
// conditions: | |
// | |
// The above copyright notice and this permission notice shall be | |
// included in all copies or substantial portions of the Software. | |
// | |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | |
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
// OTHER DEALINGS IN THE SOFTWARE. | |
#import "OGKeyPath.h" | |
@implementation OGKeyPath | |
+ (void)set:(id)kvcObject value:(id)value forExtendedKeyPathWithObjects:(id)object, ... | |
{ | |
NSMutableArray* path = [NSMutableArray array]; | |
va_list ap; | |
va_start(ap, object); | |
while (object) | |
{ | |
[path addObject:object]; | |
object = va_arg(ap, id); | |
} | |
va_end(ap); | |
[OGKeyPath set:kvcObject value:value forExtendedKeyPath:path]; | |
} | |
+ (void)set:(id)kvcObject value:(id)value forExtendedKeyPath:(NSArray *)path | |
{ | |
if ([path isKindOfClass:[NSArray class]] && [path count] > 0) | |
{ | |
NSArray *penultimatePath = [path subarrayWithRange:NSMakeRange(0, [path count] - 1)]; | |
id objectAtPenultimatePath = [OGKeyPath valueFrom:kvcObject forExtendedKeyPath:penultimatePath]; | |
id lastPathSegment = [path objectAtIndex:[path count] - 1]; | |
if ([lastPathSegment isKindOfClass:[NSString class]]) | |
{ | |
if ([objectAtPenultimatePath isKindOfClass:[NSMutableArray class]] && | |
([lastPathSegment intValue] < [objectAtPenultimatePath count])) | |
{ | |
[objectAtPenultimatePath replaceObjectAtIndex:[lastPathSegment intValue] withObject:value]; | |
} | |
else | |
{ | |
[objectAtPenultimatePath setValue:value forKey:lastPathSegment]; | |
} | |
} | |
else if ([lastPathSegment isKindOfClass:[NSNumber class]]) | |
{ | |
if ([lastPathSegment isKindOfClass:[NSMutableArray class]]) | |
{ | |
[objectAtPenultimatePath replaceObjectAtIndex:[lastPathSegment intValue] withObject:value]; | |
} | |
else | |
{ | |
NSLog(@"set:value:forExtendedKeyPath: is in the position of applying an array index %d \ | |
to a non-mutable-array object, which it can't do.", [lastPathSegment intValue]); | |
} | |
} | |
else | |
{ | |
NSLog(@"set:value:forExtendedKeyPath: encountered a path segment it can't handle."); | |
} | |
} | |
} | |
+ (id)valueFrom:(id)kvcObject forExtendedKeyPath:(NSArray *)path | |
{ | |
id currentValue = kvcObject; | |
for (id pathSegment in path) | |
{ | |
if ([pathSegment isKindOfClass:[NSString class]]) | |
{ | |
currentValue = [currentValue valueForKey:pathSegment]; | |
} | |
else if ([pathSegment isKindOfClass:[NSNumber class]]) | |
{ | |
if ([currentValue isKindOfClass:[NSArray class]]) | |
{ | |
currentValue = [currentValue objectAtIndex:[currentValue intValue]]; | |
} | |
else | |
{ | |
NSLog(@"valueFrom:forExtendedKeyPath: is in the position of applying an array index %d \ | |
to a non-array object, which it can't do.", [currentValue intValue]); | |
break; | |
} | |
} | |
else | |
{ | |
NSLog(@"valueFrom:forExtendedKeyPath: encountered a path segment it can't handle."); | |
break; | |
} | |
} | |
return currentValue; | |
} | |
+ (id)valueFrom:(id)kvcObject forExtendedKeyPathWithObjects:(id)object, ... | |
{ | |
NSMutableArray* path = [NSMutableArray array]; | |
va_list ap; | |
va_start(ap, object); | |
while (object) | |
{ | |
[path addObject:object]; | |
object = va_arg(ap, id); | |
} | |
va_end(ap); | |
return [OGKeyPath valueFrom:kvcObject forExtendedKeyPath:path]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
hello