Skip to content

Instantly share code, notes, and snippets.

@jcoleman
Forked from pnc/PCPropertyObserver.c
Last active October 9, 2015 18:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jcoleman/3554183 to your computer and use it in GitHub Desktop.
Save jcoleman/3554183 to your computer and use it in GitHub Desktop.
PCPropertyObserver
// © 2011-2014 Phillip N. Calvin, James Coleman
// For use in a setter.
// Signs up self to receive KVO notifications about given properties
// on any new value and removes self as an observer from the old value.
// For example, to observe properties of a property called customer
// (backed by ivar _customer):
// PCPropertyObserver(customer, @"allowSubscriptionPurchase", @"availableProducts");
// You'd need to write this selector yourself:
// - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
// if ([keyPath isEqualToString:@"availableProducts"] ||
// [keyPath isEqualToString:@"allowSubscriptionPurchase"]) {
// // Handle change to key
// }
// }
// KVO Path Safety:
//
// The PCKVOCheckedProperties(...) and PCKVOCheckedProperty(key) macros can
// be used to implement compiler warnings for attempts to use KVO to bind to
// non-existent properties (such as a typoed property name.)
//
// You may also use the macros to provided similar safety in your implementation of
// `observeValueForKeyPath:ofObject:change:context:`.
//
// For example, to safely observe properties of a property called customer::
// PCPropertyObserver(customer, PCKVOCheckedProperties(allowSubscriptionPurchase, availableProducts));
//
// Note: You must have Clang configured to warn on Undeclared Selector usage and define DEBUG=1.
#ifndef PC_PROPERTY_OBSERVER
#define PC_PROPERTY_OBSERVER
#if DEBUG
#define PCKVOCheckedProperty(key) NSStringFromSelector(@selector(key))
#else
#define PCKVOCheckedProperty(key) @#key
#endif
#define PC_KVO_CHECKED_PROPERTY_1(_1) PCKVOCheckedProperty(_1)
#define PC_KVO_CHECKED_PROPERTY_2(_1, _2) PC_KVO_CHECKED_PROPERTY_1(_1), PCKVOCheckedProperty(_2)
#define PC_KVO_CHECKED_PROPERTY_3(_1, _2, _3) PC_KVO_CHECKED_PROPERTY_2(_1, _2), PCKVOCheckedProperty(_3)
#define PC_KVO_CHECKED_PROPERTY_4(_1, _2, _3, _4) PC_KVO_CHECKED_PROPERTY_3(_1, _2, _3), PCKVOCheckedProperty(_4)
#define PC_KVO_CHECKED_PROPERTY_5(_1, _2, _3, _4, _5) PC_KVO_CHECKED_PROPERTY_4(_1, _2, _3, _4), PCKVOCheckedProperty(_5)
#define PC_KVO_CHECKED_PROPERTY_6(_1, _2, _3, _4, _5, _6) PC_KVO_CHECKED_PROPERTY_5(_1, _2, _3, _4, _5), PCKVOCheckedProperty(_6)
#define PC_KVO_CHECKED_PROPERTY_7(_1, _2, _3, _4, _5, _6, _7) PC_KVO_CHECKED_PROPERTY_6(_1, _2, _3, _4, _5, _6), PCKVOCheckedProperty(_7)
#define PC_KVO_CHECKED_PROPERTY_8(_1, _2, _3, _4, _5, _6, _7, _8) PC_KVO_CHECKED_PROPERTY_7(_1, _2, _3, _4, _5, _6, _7), PCKVOCheckedProperty(_8)
#define PC_KVO_CHECKED_PROPERTY_9(_1, _2, _3, _4, _5, _6, _7, _8, _9) PC_KVO_CHECKED_PROPERTY_8(_1, _2, _3, _4, _5, _6, _7, _8), PCKVOCheckedProperty(_9)
#define PC_KVO_CHECKED_PROPERTY_10(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) PC_KVO_CHECKED_PROPERTY_9(_1, _2, _3, _4, _5, _6, _7, _8, _9), PCKVOCheckedProperty(_10)
#define PC_KVO_CHECKED_PROPERTY_11(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) PC_KVO_CHECKED_PROPERTY_10(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10), PCKVOCheckedProperty(_11)
#define PC_KVO_CHECKED_PROPERTY_12(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) PC_KVO_CHECKED_PROPERTY_11(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11), PCKVOCheckedProperty(_12)
#define PC_KVO_CHECKED_PROPERTY_13(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) PC_KVO_CHECKED_PROPERTY_12(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12), PCKVOCheckedProperty(_13)
#define PC_KVO_CHECKED_PROPERTY_14(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) PC_KVO_CHECKED_PROPERTY_13(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13), PCKVOCheckedProperty(_14)
#define PC_KVO_CHECKED_PROPERTY_15(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) PC_KVO_CHECKED_PROPERTY_14(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14), PCKVOCheckedProperty(_15)
#define PC_KVO_CHECKED_PROPERTY_16(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) PC_KVO_CHECKED_PROPERTY_15(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15), PCKVOCheckedProperty(_16)
#define PC_KVO_CHECKED_PROPERTY_17(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) PC_KVO_CHECKED_PROPERTY_16(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16), PCKVOCheckedProperty(_17)
#define PC_KVO_CHECKED_PROPERTY_18(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) PC_KVO_CHECKED_PROPERTY_17(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17), PCKVOCheckedProperty(_18)
#define PC_KVO_CHECKED_PROPERTY_19(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19) PC_KVO_CHECKED_PROPERTY_18(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18), PCKVOCheckedProperty(_19)
#define PC_KVO_CHECKED_PROPERTY_20(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20) PC_KVO_CHECKED_PROPERTY_19(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19), PCKVOCheckedProperty(_20)
#define PC_KVO_CHECKED_PROPERTY_21(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21) PC_KVO_CHECKED_PROPERTY_20(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20), PCKVOCheckedProperty(_21)
#define PC_KVO_CHECKED_PROPERTY_22(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22) PC_KVO_CHECKED_PROPERTY_21(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21), PCKVOCheckedProperty(_22)
#define PC_KVO_CHECKED_PROPERTY_23(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23) PC_KVO_CHECKED_PROPERTY_22(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22), PCKVOCheckedProperty(_23)
#define PC_KVO_CHECKED_PROPERTY_24(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24) PC_KVO_CHECKED_PROPERTY_23(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23), PCKVOCheckedProperty(_24)
#define PC_KVO_CHECKED_PROPERTY_25(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25) PC_KVO_CHECKED_PROPERTY_24(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24), PCKVOCheckedProperty(_25)
#define PC_KVO_CHECKED_PROPERTY_26(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26) PC_KVO_CHECKED_PROPERTY_25(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25), PCKVOCheckedProperty(_26)
#define PC_KVO_CHECKED_PROPERTY_27(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27) PC_KVO_CHECKED_PROPERTY_26(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26), PCKVOCheckedProperty(_27)
#define PC_KVO_CHECKED_PROPERTY_28(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28) PC_KVO_CHECKED_PROPERTY_27(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27), PCKVOCheckedProperty(_28)
#define PC_KVO_CHECKED_PROPERTY_29(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29) PC_KVO_CHECKED_PROPERTY_28(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28), PCKVOCheckedProperty(_29)
#define PC_KVO_CHECKED_PROPERTY_30(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30) PC_KVO_CHECKED_PROPERTY_29(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29), PCKVOCheckedProperty(_30)
#define PC_KVO_CHECKED_PROPERTY_31(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31) PC_KVO_CHECKED_PROPERTY_30(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30), PCKVOCheckedProperty(_31)
#define PC_KVO_CHECKED_PROPERTY_32(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32) PC_KVO_CHECKED_PROPERTY_31(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31), PCKVOCheckedProperty(_32)
#define PC_GET_KVO_CHECKED_PROPERTY_MACRO_NAME(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, NAME, ...) NAME
#define PCKVOCheckedProperties(...) PC_GET_KVO_CHECKED_PROPERTY_MACRO_NAME(__VA_ARGS__, PC_KVO_CHECKED_PROPERTY_32, PC_KVO_CHECKED_PROPERTY_31, PC_KVO_CHECKED_PROPERTY_30, PC_KVO_CHECKED_PROPERTY_29, PC_KVO_CHECKED_PROPERTY_28, PC_KVO_CHECKED_PROPERTY_27, PC_KVO_CHECKED_PROPERTY_26, PC_KVO_CHECKED_PROPERTY_25, PC_KVO_CHECKED_PROPERTY_24, PC_KVO_CHECKED_PROPERTY_23, PC_KVO_CHECKED_PROPERTY_22, PC_KVO_CHECKED_PROPERTY_21, PC_KVO_CHECKED_PROPERTY_20, PC_KVO_CHECKED_PROPERTY_19, PC_KVO_CHECKED_PROPERTY_18, PC_KVO_CHECKED_PROPERTY_17, PC_KVO_CHECKED_PROPERTY_16, PC_KVO_CHECKED_PROPERTY_15, PC_KVO_CHECKED_PROPERTY_14, PC_KVO_CHECKED_PROPERTY_13, PC_KVO_CHECKED_PROPERTY_12, PC_KVO_CHECKED_PROPERTY_11, PC_KVO_CHECKED_PROPERTY_10, PC_KVO_CHECKED_PROPERTY_9, PC_KVO_CHECKED_PROPERTY_8, PC_KVO_CHECKED_PROPERTY_7, PC_KVO_CHECKED_PROPERTY_6, PC_KVO_CHECKED_PROPERTY_5, PC_KVO_CHECKED_PROPERTY_4, PC_KVO_CHECKED_PROPERTY_3, PC_KVO_CHECKED_PROPERTY_2, PC_KVO_CHECKED_PROPERTY_1)(__VA_ARGS__)
#define PCPropertyObserverWithFlags(property, flags, args...) \
NSArray *observedProperties;\
if (_ ## property != nil || property != nil) { \
observedProperties = @[ args ]; \
} \
if (_ ## property != nil) { \
for (NSString *key in observedProperties) { \
[_ ## property removeObserver:self forKeyPath:key]; \
} \
} \
_ ## property = property; \
if (property != nil) { \
for (NSString *key in observedProperties) { \
[property addObserver:self forKeyPath:key options:flags context:nil]; \
} \
}
#define PCPropertyObserver(property, args...) \
PCPropertyObserverWithFlags(property, NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial, args);
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment