{"id":9080,"date":"2014-07-06T13:47:36","date_gmt":"2014-07-06T17:47:36","guid":{"rendered":"http:\/\/mjtsai.com\/blog\/?p=9080"},"modified":"2014-07-06T13:47:37","modified_gmt":"2014-07-06T17:47:37","slug":"swizzling-and-touch-forwarding","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2014\/07\/06\/swizzling-and-touch-forwarding\/","title":{"rendered":"Swizzling and Touch Forwarding"},"content":{"rendered":"<p><a href=\"http:\/\/petersteinberger.com\/blog\/2014\/a-story-about-swizzling-the-right-way-and-touch-forwarding\/\">Peter Steinberger<\/a>:<\/p>\n<blockquote cite=\"http:\/\/petersteinberger.com\/blog\/2014\/a-story-about-swizzling-the-right-way-and-touch-forwarding\/\"><p>This works as expected in most cases, but has the issue that the original implementation will be called with a different <code>_cmd<\/code> than it expects. This can be a problem when <code>_cmd<\/code> is actually used, such as in the touch forwarding logic. I learned this the hard way after swizzling <code>touchesMoved:withEvent:<\/code> to inject additional logic. The app crashed with the popular <code>doesNotRecognizeSelector:<\/code> exception.<\/p><\/blockquote>\n<p>Instead of exchanging the method implementations, one could replace the old method and store its <code>IMP<\/code> outside the runtime. But then:<\/p>\n<blockquote cite=\"http:\/\/petersteinberger.com\/blog\/2014\/a-story-about-swizzling-the-right-way-and-touch-forwarding\/\"><p>We are now modifying the <code>touchesBegan:withEvent:<\/code> method of our custom <code>UIView<\/code> 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 swizzle <code>touchesBegan:withEvent:<\/code> on <code>UIView<\/code> directly using the same technique. Assuming <code>UIView<\/code> has no custom touch handling code, they would get the IMP from UIResponder and add a new method to <code>UIView<\/code>. But then our method gets called, which already captured the IMP of <code>UIResponder<\/code> and completely ignores the fact that we modified <code>UIView<\/code> as well.<\/p><\/blockquote>\n<p>Perhaps I&rsquo;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 <code>IMP<\/code>. Then call the old <code>IMP<\/code> 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.<\/p>","protected":false},"excerpt":{"rendered":"<p>Peter Steinberger: 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 swizzling touchesMoved:withEvent: to inject [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"","apple_news_api_id":"","apple_news_api_modified_at":"","apple_news_api_revision":"","apple_news_api_share_url":"","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[31,30,54,760,71],"class_list":["post-9080","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-ios","tag-mac","tag-objective-c","tag-objective-c-runtime","tag-programming"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/9080","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=9080"}],"version-history":[{"count":0,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/9080\/revisions"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=9080"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=9080"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=9080"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}