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
_cmdthan it expects. This can be a problem when_cmdis 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 customUIViewsubclass. 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:onUIViewdirectly using the same technique. AssumingUIViewhas 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 ofUIResponderand completely ignores the fact that we modifiedUIViewas 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.