It’s clear that we have a problem. We can’t log Firebase calls to setObject:forKey.
So we have the following options:
- Send email to Google and ask them to use our mySetObject:forKey.
- Use method swizzling.
- Some other hacky solution that I can’t think of right now.
So obviously we will proceed with option two (But if you decide to send email to Google please cc me. I would like to see their reaction 😂 ha ha ha).
The solution – I can think of
#import "NSUserDefaults+MonitoringWrites.h" #import <objc/runtime.h> @implementation NSUserDefaults (MonitoringWrites) + (void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ Class class = [self class]; SEL defaultSelector = @selector(setObject:forKey:); SEL swizzledSelector = @selector(swizzled_setObject:forKey:); Method defaultMethod = class_getInstanceMethod(class, defaultSelector); Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); BOOL isMethodExists = !class_addMethod(class, defaultSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); if (isMethodExists) { method_exchangeImplementations(defaultMethod, swizzledMethod); } else { class_replaceMethod(class, swizzledSelector, method_getImplementation(defaultMethod), method_getTypeEncoding(defaultMethod)); } }); } #pragma mark - Method Swizzling - (void)swizzled_setObject:(id)value forKey:(NSString *)defaultName { [self iwsSetObject:value forKey:defaultName]; NSLog(@"Set Object %@ for key %@",value,defaultName); } @end
Method, Selector and Implementation for Swizzle
SEL defaultSelector = @selector(setObject:forKey:); SEL swizzledSelector = @selector(swizzled_setObject:forKey:); Method defaultMethod = class_getInstanceMethod([self class], defaultSelector); Method swizzledMethod = class_getInstanceMethod([self class], swizzledSelector); BOOL isMethodExists = !class_addMethod([self class], defaultSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
Tricky part we approached
BOOL isMethodExists = !class_addMethod([self class], defaultSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); if (isMethodExists) { method_exchangeImplementations(defaultMethod, swizzledMethod); } else { class_replaceMethod([self class], swizzledSelector, method_getImplementation(defaultMethod), method_getTypeEncoding(defaultMethod)); }