There is no sanctioned way to be notified when a method executes, unless it specifically notes that it returns a notification, or a pointer to some kind of callback, a block, etc. While swizzling may be one way of going about it, proxying is probably your best bet. Instead of messing with the selector for an entire class, you interpose yourself "as" the class by implementing all its properties and/or forwarding selectors to the target object. In this way, NSProxy and subclasses can be used as wrappers around normal objects, meaning you can respond to any kind of method that happens to be sent through your proxy before forwarding it on to the target. A simple proxy can be modeled after the sample below:
FOUNDATION_EXPORT NSString *const CFIProxyDidInitializeTargetNotification;
@interface CFIObjectProxy : NSProxy {
__strong Foo *_target;
}
- (id)init;
@property(nonatomic, readonly, retain) NSArray* bars;
@end
//...
#import "CFIObjectProxy.h"
NSString *const CFIProxyDidInitializeTargetNotification = @"CFIProxyDidInitializeTargetNotification";
@implementation CFIObjectProxy
- (id)init {
_target = [[Foo alloc]init];
[NSNotificationCenter.defaultCenter postNotificationName:CFIProxyDidInitializeTargetNotification object:nil];
return self;
}
- (void)forwardInvocation:(NSInvocation *)invocation {
[invocation invokeWithTarget:_target];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
return [_target methodSignatureForSelector:sel];
}
- (NSString *)description {
return [_target description];
}
- (NSString *)debugDescription {
return [NSString stringWithFormat:@"<%@:%p> Proxy for Object: %@", NSStringFromClass(self.class), self, _target];
}
- (NSArray*)bars {
return [_target bars];
}
@end