rentzsch / jrswizzle

one-stop-shop for all your method swizzling needs
MIT License
2.66k stars 416 forks source link

Result of invocation in block is freed before it can be used #22

Open JetForMe opened 5 years ago

JetForMe commented 5 years ago

I attempted to swizzle the class method JSONObjectWithData:options:error: like this:

+ (void)
load
{
    static dispatch_once_t      sInitToken;
    dispatch_once(&sInitToken,
    ^{
        __block NSInvocation* invocation = nil;
        NSError* err = nil;
        invocation = [self jr_swizzleClassMethod: @selector(JSONObjectWithData:options:error:)
                            withBlock:
                            ^(id inObj, NSData* inData, NSJSONReadingOptions inOptions, NSError** outError)
                            {
                                NSLog(@"before %@", inObj);

                                NSInvocation* inv = [invocation copy];

                                [inv setArgument: &inData atIndex: 2];
                                [inv setArgument: &inOptions atIndex: 3];
                                [inv setArgument: &outError atIndex: 4];

                                [inv invokeWithTarget: inObj];

                                id ret = nil;
                                [inv getReturnValue: &ret];

                                NSLog(@"after %@", inObj);

                                return ret;
                            }
                            error: &err];
            if (invocation == nil)
            {
                NSLogDebug(@"Error swizzling NSJSONSerialization: %@", err);
            }
    });
}

But unfortunately this doesn't seem to work, as the returned dictionary gets released before a later call to objc_retainAutoreleasedReturnValue() deep inside iOS, causing a crash. Enabling Zombie objects shows:

*** -[__NSDictionaryI retain]: message sent to deallocated instance 0x600002611440
JetForMe commented 5 years ago

Interestingly, doing the same thing with regular methods works fine. I wonder if this is an ARC bug.

zhongshucheng commented 4 years ago

Have you found the solution, sir?

JetForMe commented 4 years ago

Wow, sorry, I can't even remember why I wrote this code.

zhongshucheng commented 4 years ago

I wrote this code was for testing in my script. I just found the invocation won't be released if I used a property to hold it. So it is not a problem now. Thanks anyway.