Swizzling and Touch Forwarding
This works as expected in most cases, but has the issue that the original implementation will be called with a different
_cmd
than it expects. This can be a problem when_cmd
is actually used, such as in the touch forwarding logic. I learned this the hard way after swizzlingtouchesMoved:withEvent:
to inject additional logic. The app crashed with the populardoesNotRecognizeSelector:
exception.
Instead of exchanging the method implementations, one could replace the old method and store its IMP
outside the runtime. But then:
We are now modifying the
touchesBegan:withEvent:
method of our customUIView
subclass. There is no default implementation yet, so we get the IMP from UIResponder and then manually call this. Imagine if at some later point, somebody else would swizzletouchesBegan:withEvent:
onUIView
directly using the same technique. AssumingUIView
has no custom touch handling code, they would get the IMP from UIResponder and add a new method toUIView
. But then our method gets called, which already captured the IMP ofUIResponder
and completely ignores the fact that we modifiedUIView
as well.
Perhaps I’m missing something, but it seems like it would be possible to exchange the method implementations. When you need to call the old method, use the new selector to fetch the old IMP
. Then call the old IMP
passing in the old selector. Then the old method would still receive its expected selector, and you would still be safe if other code swizzles the same method.