johnno1962 / Xtrace

Trace Objective-C method calls by class or instance
MIT License
1.83k stars 132 forks source link

get self object #5

Closed iamredeye closed 10 years ago

iamredeye commented 10 years ago

Hello,

Thanks for the XTrace projet, it is awesome !!!

Simply I would like to know how could I get the self object from which the method is intercepted. Here is an example : I would like to intercept the before of any UIViewController subclass, so I added this code : [Xtrace forClass:[self class] before:@selector(viewWillAppear:) callback:@selector(beforeViewWillAppear:sender:)];

When I go to my interception method and I would like to display sender, It says that this object is always (null) : +(void)beforeViewWillAppear:(BOOL)animated sender:(id)sender { NSLog(@"%@",sender); }

How could I pass the sender object to my interceptions methods in my delegate ?

Thanks in advance.

johnno1962 commented 10 years ago

Hi, I think you have the animate and sender arguments of your intercept back to front. The first argument is “self” then any arguments. If this doesn’t work, can you send me a small example project?

iamredeye commented 10 years ago

It works great....thank you very much... Simply I do have another simple question, I liked to add an interceptor before and after method "view Did Load" for all the UIViewControllers subclasses. So I added this code to my app delegate :

[Xtrace forClass:[UIViewController class] before:@selector(viewDidLoad:) callback:@selector(beforeViewDidLoad:)];

Then I go and add in my PlayersViewController this code : -(void)viewDidLoad { NSLog(@"begin players view did load"); [super viewDidLoad]; NSLog(@"end players view did load"); }

The problem is when I put an interceptor to the class UIViewController which the mother class for all views I get the message "begin players view did load" in my console log before executing the interception callback method.

How could I fix this issue ?

Thanks again

johnno1962 commented 10 years ago

You are intercepting [UIViewController viewDidLoad] not the version in your own class so it is the [super viewDidLoad] which will be intercepted. You should try: [Xtrace forClass:[PlayersViewController class] before:@selector(viewDidLoad:) callback:@selector(beforeViewDidLoad:)];

iamredeye commented 10 years ago

Thanks, It is working... Is there a solution to try to intercept all UIViewControllers subclasses's viewDidLoad method without putting the name of each view controller (Here : PlayersViewControllers) ? I'm looking for a automated way, which can intercept at runtime the creation of an object suclasses from UIViewController and then inserting interceptions for it

johnno1962 commented 10 years ago

You’d need to do something like:

unsigned ccount;
Class *classes = objc_copyClassList( &ccount );
for ( unsigned i=0 ; i<ccount ; i++ ) {
   if ( class_getSuperclass(classes[i]) == [UIViewController class] )
       [Xtrace forClass: classes[i] before:@selector(viewWillAppear:) callback:@selector(beforeViewWillAppear:sender:)];
}
free( classes );
iamredeye commented 10 years ago

Thanks a lot ! it works