-
-
Save jcoleman/3554183 to your computer and use it in GitHub Desktop.
PCPropertyObserver
This file contains hidden or 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
// © 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