RACEXTKeyPathCoding.h 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. //
  2. // EXTKeyPathCoding.h
  3. // extobjc
  4. //
  5. // Created by Justin Spahr-Summers on 19.06.12.
  6. // Copyright (C) 2012 Justin Spahr-Summers.
  7. // Released under the MIT license.
  8. //
  9. #import <Foundation/Foundation.h>
  10. #import "RACmetamacros.h"
  11. /**
  12. * \@keypath allows compile-time verification of key paths. Given a real object
  13. * receiver and key path:
  14. *
  15. * @code
  16. NSString *UTF8StringPath = @keypath(str.lowercaseString.UTF8String);
  17. // => @"lowercaseString.UTF8String"
  18. NSString *versionPath = @keypath(NSObject, version);
  19. // => @"version"
  20. NSString *lowercaseStringPath = @keypath(NSString.new, lowercaseString);
  21. // => @"lowercaseString"
  22. * @endcode
  23. *
  24. * ... the macro returns an \c NSString containing all but the first path
  25. * component or argument (e.g., @"lowercaseString.UTF8String", @"version").
  26. *
  27. * In addition to simply creating a key path, this macro ensures that the key
  28. * path is valid at compile-time (causing a syntax error if not), and supports
  29. * refactoring, such that changing the name of the property will also update any
  30. * uses of \@keypath.
  31. */
  32. #define keypath(...) \
  33. metamacro_if_eq(1, metamacro_argcount(__VA_ARGS__))(keypath1(__VA_ARGS__))(keypath2(__VA_ARGS__))
  34. #define keypath1(PATH) \
  35. (((void)(NO && ((void)PATH, NO)), strchr(# PATH, '.') + 1))
  36. #define keypath2(OBJ, PATH) \
  37. (((void)(NO && ((void)OBJ.PATH, NO)), # PATH))
  38. /**
  39. * \@collectionKeypath allows compile-time verification of key paths across collections NSArray/NSSet etc. Given a real object
  40. * receiver, collection object receiver and related keypaths:
  41. *
  42. * @code
  43. NSString *employessFirstNamePath = @collectionKeypath(department.employees, Employee.new, firstName)
  44. // => @"employees.firstName"
  45. NSString *employessFirstNamePath = @collectionKeypath(Department.new, employees, Employee.new, firstName)
  46. // => @"employees.firstName"
  47. * @endcode
  48. *
  49. */
  50. #define collectionKeypath(...) \
  51. metamacro_if_eq(3, metamacro_argcount(__VA_ARGS__))(collectionKeypath3(__VA_ARGS__))(collectionKeypath4(__VA_ARGS__))
  52. #define collectionKeypath3(PATH, COLLECTION_OBJECT, COLLECTION_PATH) ([[NSString stringWithFormat:@"%s.%s",keypath(PATH), keypath(COLLECTION_OBJECT, COLLECTION_PATH)] UTF8String])
  53. #define collectionKeypath4(OBJ, PATH, COLLECTION_OBJECT, COLLECTION_PATH) ([[NSString stringWithFormat:@"%s.%s",keypath(OBJ, PATH), keypath(COLLECTION_OBJECT, COLLECTION_PATH)] UTF8String])