Re: Switching methods in private classes in Apple frameworks
Re: Switching methods in private classes in Apple frameworks
- Subject: Re: Switching methods in private classes in Apple frameworks
- From: Scott Morrison <email@hidden>
- Date: Fri, 12 Mar 2010 07:16:04 -0500
You can access ivars
just
#include "objc/objc-class.h"
and then use
static Ivar theIvar; //create a static to cache the ivar information
if (!theIvar) theIvar = class_getInstanceVariable([self class], "ivarName"); //look up the ivar information and cache it
id aValue = object_getIvar(self, ivar); //get the ivar
object_setIvar(self,ivar,value); //this is an assignment, you are responsible for memory management!
There are a few gotchas if your ivar is not an NSObject .
For sending a message to the super.
[super amessage] won't work because super is compile and will referred not to the super of self, but the super of the class containing the swizzled in message
However the runtime can come to the rescue again by looking up the real super of self and sending a message to it.
objc_msgSendSuper(&(struct objc_super){self, class_getSuperclass([self class])},_cmd, ...)
set up a macro
#define SUPER(...) objc_msgSendSuper(&(struct objc_super){self, class_getSuperclass([self class])},_cmd, ##__VA_ARGS__)
and then
SUPER(my,argument,List);
of course this is assuming you are getting a void or NSObject * reuturn, if a different return type, you have to change things up.
/* insert warnings about how method swizzling is evil and should never be used, especially in production code, and how civilization as we know it will collapse if you use it.*/
On 2010-03-12, at 5:36 AM, Daniel DeCovnick wrote:
> Wow, that's really, really awesome.
>
> Do you have any more details on why you can't use ivars? Not calling super makes sense. Can you access properties?
> On Mar 11, 2010, at 8:58 PM, Gideon King wrote:
>
>> Thanks Jerry, I should mention that I did get this caveat note from Greg Parker (Apple's "runtime wrangler"):
>>
>> "..you must be cautious about what your replacement method does. In particular, you must not use any of the class's ivars and you must not call [super something]. As long as you follow those, you can swap in a method from any class, or even a C function with a matching argument list."
>>
>> So as long as you are careful about what you do, yes it is entirely possible to replace methods at will. I hope nobody misuses it, but it certainly was essential in my debugging - yes, I found it! Yay!
>>
>> Essentially what appeared to be happening was that I had a notification queued which had an object in it which held a reference to a managed object, but by the time the notification was destroyed, the managed object had turned to a fault (but was not released because the notification was causing it to be retained), and the managed object context had been released as part of the document deallocation, so when my object tried to access the managed object, it tried to fire the fault on a freed managed object context...or something like that. Even if that's not exactly right in every detail, I now have the conceptual understanding of the problem and believe I will be able to fix it. What a relief!
>>
>> Regards
>>
>> Gideon
>>
>> On 12/03/2010, at 1:54 PM, Jerry Krinock wrote:
>>
>>>
>>> On 2010 Mar 11, at 18:00, Gideon King wrote:
>>>
>>>> This is really cool...so I can replace a method without being a subclass or category.
>>>
>>> I just need to chime in here, in case anyone missed it, to emphasize how *ALL-CAPS COOL* this is indeed.
>>>
>>> In the ReadMe of Apple's MethodReplacement.zip sample code, it states "The trick is to define a category on the class whose method you want to replace." We have just learned that this sentence is incorrect. You do *not* need to define a category on the class whose method you want to replace.
>>>
>>> As Gideon showed in his code, the first argument of class_getInstanceMethod() need *not* be self, and therefore you can replace any method in *any* class, even a private one that's unknown to the SDK, with any other method in *any class*, even a different class.
>>>
>>> This makes Method Replacement much more powerful in debugging, and even patching bugs in Cocoa.
>>>
>>> I just sent Apple a "wasn't helpful" gram on that ReadMe.
>>>
>>> Thanks, Gideon. I hope you've found out who's sending that notification releasing your moc :)
>>>
>>
>> _______________________________________________
>>
>> Cocoa-dev mailing list (email@hidden)
>>
>> Please do not post admin requests or moderator comments to the list.
>> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>>
>> Help/Unsubscribe/Update your Subscription:
>>
>> This email sent to email@hidden
>
> _______________________________________________
>
> Cocoa-dev mailing list (email@hidden)
>
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden