Swizzling methods that implicitly return a stored object under ARC

For example, consider the following code under ARC:

#import <Foundation/Foundation.h> #import <objc/runtime.h> @implementation NSDate (MyEvilHack) + (void)load { Method originalMethod = class_getInstanceMethod(self, @selector(copyWithZone:)); Method newMethod = class_getInstanceMethod(self, @selector(myCopyWithZone:)); method_exchangeImplementations(originalMethod, newMethod); } - (id)myCopyWithZone:(NSZone *)zone { id result = [self myCopyWithZone:zone]; // do customization return result; } @end 

In this code, the original copyWithZone: method implicitly returns the stored object because it belongs to the copy method family. But my myCopyWithZone: not.

I expect a crash, but it looks like this code is working fine. Of course, I can rename my method to avoid confusion. But I'm curious what exactly is going on under the hood?

+5
source share
1 answer

As you know, ARC checks the method name, applies Cocoa's memory management naming conventions, and determines how the method should behave. For the method that it compiles, it forces the method to obey these conventions. For the method that it invokes, it assumes that the method obeys these conventions.

(You can override conventions using function attributes, but ignore this for now.)

When ARC compiles your -myCopyWithZone: it determines that such a method should return a +0 link. When it encounters a call to (apparently) -myCopyWithZone: it assumes the method returns a +0 link. Since they coincide, he must neither save nor release anything. (Well, it can temporarily save the result, but it should balance it with auto-advertising.) As a result, the actual +1 link returned by the original -copyWithZone: is saved for the caller and the caller expected +1 links, so all is good.

You can probably make ARC mess by calling another method (which will not be effectively renamed swizzling), which returns a +1 link. If he was to return this, and since the current method is expected to return a +0 link, it will automatically stop it. The caller did not save it because it was expecting a +1 link. Thus, the object will be prematurely released, which can lead to failure.

+4
source

Source: https://habr.com/ru/post/1243354/


All Articles