iOS hot Update-jspatch Implementation principle +patch onsite Recovery

Source: Internet
Author: User
<span id="Label3"></p>About Hotfixpatch<p><p>In the area of iOS development, because of Apple's stringent auditing standards and inefficiencies, iOS apps are extremely slow to release, with a slightly larger version of the app almost one months old, so code hot update (hotfixpatch) is especially important for iOS apps.</p></p><p><p>Now the industry is basically using the Waxpatch scheme, because the wax framework has been discontinued for four or five years, so waxpatch in the use of the process there are still many pits (such as the problem of parameter conversion process, if the inheriting class is not instantiated to modify the method of inheriting class is invalid, Wax_ Delayed release of instance held in the GC for OC ...). In addition, Apple's attitude to the use of wax is also in a vague state, which is also a potential use of Risk.</p></p><p><p>With the Facebook open source react native framework, using Javascriptcore.framework to directly build bridge between JavaScript (JS) and Objective-c (OC) is possible, Jspatch was born at this Time. The first is from the Tang Qiao public number push to understand, began to think is react native on the basis of the package, but recently carefully studied the source code, with react native half a dime relationship is not, here first to the author of Jspatch (not Tang qiao, is bang, Blog Address) likes One.</p></p><p><p>After an in-depth look at jspatch, the first feeling is that the scheme is small, easy to understand, low maintenance, and directly through the OC code to call the runtime api, as an iOS developer, will soon be able to understand, do not have to spend a lot of effort to understand learning Lua. In addition, in the establishment of JS and OC bridge, The author very clever use of JS and OC Two language message forwarding mechanism to do a very elegant implementation, slightly less is jspatch can only support iOS7 and Above.</p></p><p><p>Since some of the Company's applications are still supporting ios6, completely replace the wax is not realistic, but some new applications have directly started to support ios7. Personally think IOS6 and iOS7 interface style difference is large, I believe that the application of the minimum support version will be upgraded to iOS7 Soon. Also taking into account the Jspatch maturity is not enough, so decided to combine Jspatch and waxpatch, complementary to Use. Below to tell you some of the experience of learning to Use.</p></p>Comparison of Jspatch and Waxpatch<p><p>For the advantages of Jspatch vs waxpatch, Take a look at the Jspatch author's words:</p></p> <ul> <ul> <li>source: jspatch– Dynamic Update iOS APP</li> </ul> </ul>Scenario Comparison<p><p>There are a number of scenarios where dynamic patching can be implemented, such as waxpatch, which can be used with LUA to invoke the OC method, relative to the Waxpatch,jspatch advantage:</p></p> <ul> <ul> <li><p>1.<strong>js language:</strong> JS than Lua in the field of application development has a broader application, the current front-end development and terminal development has a convergence trend, as an extension of the scripting language, JS is the perfect choice.</p></li> <li><p>2. <strong>comply with Apple rules:</strong> Jspatch is more consistent with Apple's Rules. IOS Developer Program License Agreement 3.3.2 mentions that executable code cannot be issued dynamically, except for code executed by Apple Javascriptcore.framework or webkit, JS is executed by Javascriptcore.framework.</p></li> <li><p>3. <strong>compact:</strong> using the system built-in javascriptcore.framework, no embedded scripting engine, small Size.</p></li> <li><p>4. <strong>Support Block:</strong> Wax stopped development and maintenance several years ago, does not support the OBJECTIVE-C block and Lua program, although some third parties have implemented block, but the use of parameters there are more restrictions.</p></li> </ul> </ul><p><p>Disadvantages of Jspatch:</p></p> <ul> <ul> <li>The disadvantage with respect to Waxpatch,jspatch is that iOS6 is not supported because Javascriptcore.framework is Required. In addition, the current memory usage will be higher than wax, continuous improvement.</li> </ul> </ul>Understanding of the realization principle of Jspatch<p><p>Jspatch the implementation of the principle of the Author's blog has been very detailed introduction, I do not say more here, paste the learning place:</p></p> <ul> <ul> <li>Jspatch Implementation principle Detailed http://blog.cnbang.net/tech/2808/</li> <li>Jspatch git source code and usage instructions Https://github.com/bang590/JSPatch</li> </ul> </ul><p><p>Look at the implementation of the principle of detail when the control of the source to see, a better understanding, I am here to say my study and understanding of Jspatch:</p></p>(1) Dynamic language characteristics of OC<p><p>Regardless of the Waxpatch framework or the Jspatch scheme, the fundamental principle is to make use of the dynamic language characteristics of OC to dynamically modify the method of the class.<br>The dynamic language features of OC are implemented on the runtime system (all implemented in c, Apple maintains an open source code), and the object-oriented class and instance mechanisms are based on the message Mechanism. What we usually think of as [object method], the correct understanding should be [receiver sendmsg], all the message sent in the compilation phase compiled into the runtime C function call: _obj_sendmsg (id, SEL).</p></p><p><p>For more information, refer to the Blog:</p></p> <ul> <ul> <li>OBJECTIVE-C Runtime Detailed Introduction</li> <li>OBJECTIVE-C Runtime Source _apple</li> </ul> </ul><p><p>Runtime provides some API to run time</p></p> <ul> <ul> <li>Reflection classes and selectors</li> </ul> </ul><pre class="hljs objectivec"><pre class="hljs objectivec"><code class="objectivec"> <span class="hljs-built_in">NSClassFromString</span>(<span class="hljs-string">"UIViewController"</span>); <span class="hljs-built_in">NSSelectorFromString</span>(<span class="hljs-string">"viewDidLoad"</span>);</code></pre></pre> <ul> <ul> <li>Add or replace the implementation of the method selector (SEL) for a class (IMP)</li> </ul> </ul><pre class="hljs cs"><pre class="hljs cs"><code class="cs"> <span class="hljs-function">BOOL <span class="hljs-title">class_addMethod</span>(<span class="hljs-params">Class cls, SEL name, IMP imp, <span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span> *types</span>)</span>; <span class="hljs-function">IMP <span class="hljs-title">class_replaceMethod</span>(<span class="hljs-params">Class cls, SEL name, IMP imp, <span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span> *types</span>)</span>;</code></pre></pre> <ul> <ul> <li>Dynamically registering classes in runtime</li> </ul> </ul><pre class="hljs lisp"><pre class="hljs lisp"><code class="lisp"> Class superCls = NSClassFromString<span class="hljs-list">(<span class="hljs-keyword">superClassName</span>)</span><span class="hljs-comment">;</span> cls = objc_allocateClassPair<span class="hljs-list">(<span class="hljs-keyword">superCls</span>, className.UTF8String, <span class="hljs-number">0</span>)</span><span class="hljs-comment">;</span> objc_registerClassPair<span class="hljs-list">(<span class="hljs-keyword">cls</span>)</span><span class="hljs-comment">;</span></code></pre></pre>(2) JS how to call OC<p><p>In the JS runtime environment, there are two problems to be solved, one is the acquisition of the OC class object (objc_class), and the other is to use the interface method provided by the Object.</p></p><p><p>For the first problem, Jspatch in the implementation is through the require call in the JS environment to create a class with the same name of the object (js form), when sent to OC Alloc receive the message, will be created in the OC environment to save the object address to this JS object in the same name, JS itself does not complete the initialization of any Object. The reference to JS holding OC objects is explained in the Jspatch Author's blog post, with no specific tests. See Jspatch.js Code:</p></p><pre class="hljs scala"><code class="scala"> <span class="hljs-comment"><span class="hljs-comment">//request OC Class object</span></span> <span class="hljs-type"><span class="hljs-type">UIView</span></span>= Require (<span class="hljs-string"><span class="hljs-string">"UIView"</span></span>);<span class="hljs-comment"><span class="hljs-comment">//cache JS class object with the same name</span></span> <span class="hljs-keyword"><span class="hljs-keyword">var</span></span>_require = function (clsname) {<span class="hljs-keyword"><span class="hljs-keyword">if</span></span>(!global[clsname]) {global[clsname] = {__iscls:<span class="hljs-number"><span class="hljs-number">1</span></span>, __clsname:clsname}}<span class="hljs-keyword"><span class="hljs-keyword">return</span></span>global[clsname]}<span class="hljs-comment"><span class="hljs-comment">//call The class method to return the OC Instantiation object for encapsulation</span></span> <span class="hljs-keyword"><span class="hljs-keyword">var</span></span>RET = instance? _oc_calli (instance, selectorname, args, issuper): _oc_callc (clsname, selectorname, Args)<span class="hljs-comment"><span class="hljs-comment">//oc return object after creation</span></span> <span class="hljs-keyword"><span class="hljs-keyword">return</span></span>@{@<span class="hljs-string"><span class="hljs-string">"__clsname"</span></span>:<span class="hljs-type"><span class="hljs-type">Nsstringfromclass</span></span>([obj<span class="hljs-class"><span class="hljs-class"> <span class="hljs-keyword">class</span>]), <span class="hljs-title">@</span>"<span class="hljs-title">__obj</span>":</span></span>obj};<span class="hljs-comment"><span class="hljs-comment">Resolving OC Objects In//js</span></span> <span class="hljs-keyword"><span class="hljs-keyword">return</span></span>_formatoctojs (ret)<span class="hljs-comment"><span class="hljs-comment">//_formatoctojs</span></span> <span class="hljs-keyword"><span class="hljs-keyword">if</span></span>(obj instanceof<span class="hljs-type"><span class="hljs-type">Object</span></span>) {<span class="hljs-keyword"><span class="hljs-keyword">var</span></span>RET = {}<span class="hljs-keyword"><span class="hljs-keyword"></span> for</span>(<span class="hljs-keyword"><span class="hljs-keyword">var</span></span>Key in Obj) {ret[key] = _formatoctojs (obj[key])}<span class="hljs-keyword"><span class="hljs-keyword">return</span></span>ret}</code></pre><p><p>For the second problem, Jspatch in the JS environment through the central forwarding method, all OC method calls through the new Object (js) prototype method _c (methodName) to complete the call, before the JS script through JavaScriptCore execution, Replace All method call characters first<br>_c (' method ') method, in _c function through the Jscontex established bridge function passed in the parameters and the return parameter is completed the call;</p></p><pre class="hljs objectivec"><code class="objectivec"> <span class="hljs-comment"><span class="hljs-comment">//character Substitution</span></span> <span class="hljs-keyword"><span class="hljs-keyword">Static</span></span> <span class="hljs-built_in"><span class="hljs-built_in">NSString</span></span>*_regexstr =<span class="hljs-string"><span class="hljs-string">@ "\\.\\s* (\\w+) \\s*\\ ("</span></span>;<span class="hljs-keyword"><span class="hljs-keyword">Static</span></span> <span class="hljs-built_in"><span class="hljs-built_in">NSString</span></span>*_replacestr =<span class="hljs-string"><span class="hljs-string">@ ". __c (\" $1\ ") ("</span></span>;<span class="hljs-built_in"><span class="hljs-built_in">NSString</span></span>*formatedscript = [<span class="hljs-built_in"><span class="hljs-built_in">NSString</span></span>Stringwithformat:<span class="hljs-string"><span class="hljs-string">@ "try{@}catch (e) {_oc_catch (e.message, e.stack)}"</span></span>, [_regex Stringbyreplacingmatchesinstring:script options:<span class="hljs-number"><span class="hljs-number">0</span></span>Range<span class="hljs-built_in"><span class="hljs-built_in">Nsmakerange</span></span>(<span class="hljs-number"><span class="hljs-number">0</span></span>, script<span class="hljs-variable"><span class="hljs-variable">. Length</span></span>) [withtemplate:_replacestr]];<span class="hljs-comment"><span class="hljs-comment">//__c () Forwarding call parameters to OC</span></span>Object<span class="hljs-variable"><span class="hljs-variable">. Prototype</span></span><span class="hljs-variable"><span class="hljs-variable">. __c</span></span>= function (methodName) {...<span class="hljs-keyword"><span class="hljs-keyword">return</span></span>function () {var args = Array<span class="hljs-variable"><span class="hljs-variable">. Prototype</span></span><span class="hljs-variable"><span class="hljs-variable">. Slice</span></span><span class="hljs-variable"><span class="hljs-variable">.</span> call</span>(arguments)<span class="hljs-keyword"><span class="hljs-keyword">return</span></span>_methodfunc (<span class="hljs-keyword"><span class="hljs-keyword"></span> self</span><span class="hljs-variable"><span class="hljs-variable">. __obj</span></span>,<span class="hljs-keyword"><span class="hljs-keyword"></span> self</span><span class="hljs-variable"><span class="hljs-variable">. __clsname</span></span>, methodName, args,<span class="hljs-keyword"><span class="hljs-keyword"></span> self</span><span class="hljs-variable"><span class="hljs-variable">. __issuper</span></span>) } }<span class="hljs-comment"><span class="hljs-comment">//_methodfunc Call bridge function</span></span>var _methodfunc = function (instance, clsname, methodName, args, issuper) {... var ret = instance? _oc_call I (instance, selectorname, args, issuper): _oc_callc (clsname, selectorname, Args)<span class="hljs-keyword"><span class="hljs-keyword">return</span></span>_formatoctojs (ret)}<span class="hljs-comment">Bridge functions <span class="hljs-comment">in//oc, The bridge functions of JS and OC are defined by this</span></span>context[<span class="hljs-string"><span class="hljs-string">@ "_oc_calli"</span></span>] = ^<span class="hljs-keyword"><span class="hljs-keyword">ID</span></span>(jsvalue *obj,<span class="hljs-built_in"><span class="hljs-built_in">NSString</span></span>*selectorname, Jsvalue *arguments,<span class="hljs-built_in"><span class="hljs-built_in">BOOL</span></span>Issuper) {<span class="hljs-keyword"><span class="hljs-keyword">return</span></span>Callselector (<span class="hljs-literal"><span class="hljs-literal">Nil</span></span>, selectorname, arguments, obj, issuper); }; context[<span class="hljs-string"><span class="hljs-string">@ "_oc_callc"</span></span>] = ^<span class="hljs-keyword"><span class="hljs-keyword">ID</span></span>(<span class="hljs-built_in"><span class="hljs-built_in">NSString</span></span>*classname,<span class="hljs-built_in"><span class="hljs-built_in">NSString</span></span>*selectorname, Jsvalue *arguments) {<span class="hljs-keyword"><span class="hljs-keyword">return</span></span>Callselector (className, selectorname, arguments,<span class="hljs-literal"><span class="hljs-literal">Nil</span></span>,<span class="hljs-literal"><span class="hljs-literal">NO</span></span>); };</code></pre>(3) JS How to replace OC method<p><p>The main function of Jspatch is to fix some online bugs through a script, hoping to achieve the goal of replacing the OC Method. The clever thing about Jspatch is that it utilizes the message forwarding mechanism of OC.</p></p> <ul> <ul> <li>1: Replace the original selector IMP implementation for an empty imp implementation, so that when the Objc_class received the message, the message will be forwarded, in addition to the initial implementation of selector to save;</li> </ul> </ul><pre class="hljs objectivec"><code class="objectivec"> <span class="hljs-comment"><span class="hljs-comment">//selector pointing to an empty implementation</span></span>IMP msgforwardimp = Getemptymsgforwardimp (typedescription, methodsignature); Class_replacemethod (cls, selector, msgforwardimp, typedescription);<span class="hljs-comment"><span class="hljs-comment">//save Original implementation, modified here, added support for recovery site</span></span> <span class="hljs-built_in"><span class="hljs-built_in">NSString</span></span>*originalselectorname = [<span class="hljs-built_in"><span class="hljs-built_in">NSString</span></span>Stringwithformat:<span class="hljs-string"><span class="hljs-string">@ "[email protected]"</span></span>, selectorname]; SEL Originalselector =<span class="hljs-built_in"><span class="hljs-built_in">nsselectorfromstring</span></span>(originalselectorname);<span class="hljs-keyword"><span class="hljs-keyword">if</span></span>(class_respondstoselector (cls, Selector)) {<span class="hljs-keyword"><span class="hljs-keyword">if</span></span>(!class_respondstoselector (cls, Originalselector)) {class_addmethod (cls, originalselector, originalimp, typedescription); }<span class="hljs-keyword"><span class="hljs-keyword">Else</span></span>{class_replacemethod (cls, originalselector, originalimp, typedescription); } }</code></pre> <ul> <ul> <li>2: the replacement JS method constructs a jpselector and its IMP implementation (constructed according to the return parameters), added to the current class, and through the CLS+SELECOTR global cache JS Method (the Global Cache is not much use, but for the later recovery site is useful);</li> </ul> </ul><pre class="hljs php"><pre class="hljs php"><code class="php"> <span class="hljs-keyword">if </span> (!_jsoveridemethods[clsname][ Jpselectorname]) {_initjpoveridemethods (clsname); _jsoveridemethods[clsname][jpselectorname] = <span class="hljs-function"><span class="hljs-keyword">function </span></span>; <span class="hljs-keyword">const </span> char *returntype = [methodsignature methodreturntype]; IMP jpimplementation = <span class="hljs-keyword">null </span>; <span class="hljs-comment">//constructs </span> based on the return type <span class="hljs-keyword">switch </span> (returntype[<span class="hljs-number">0 </span>]) { ... } <span class="hljs-keyword">if </span> (!class_respondstoselector (cls, Jpselector)) {class_addmethod (cls, jpselector, jpimplementation, typedescription); } <span class="hljs-keyword">else </span> {class_replacemethod (cls, jpselector, jpimplementation,typedescriptio n); } }</code></pre></pre> <ul> <ul> <li>3: then rewrite the forwadinvocation implementation of each substitution method class to intercept, if the intercepted invocation Selctor converted to Jpselector can respond, the description is a replacement method, The imp of Jpselector is called after taking the parameter from invocation;</li> </ul> </ul><pre class="hljs objectivec"><code class="objectivec"> <span class="hljs-keyword"><span class="hljs-keyword">Static</span></span> <span class="hljs-keyword"><span class="hljs-keyword">void</span></span>Jpforwardinvocation (<span class="hljs-keyword"><span class="hljs-keyword">ID</span></span>slf, SEL selector,<span class="hljs-built_in"><span class="hljs-built_in">nsinvocation</span></span>*invocation) {<span class="hljs-built_in"><span class="hljs-built_in">nsmethodsignature</span></span>*methodsignature = [invocation methodsignature];<span class="hljs-built_in"><span class="hljs-built_in">Nsinteger</span></span>numberofarguments = [methodsignature numberofarguments];<span class="hljs-built_in"><span class="hljs-built_in">NSString</span></span>*selectorname =<span class="hljs-built_in"><span class="hljs-built_in">Nsstringfromselector</span></span>(invocation<span class="hljs-variable"><span class="hljs-variable">. Selector</span></span>);<span class="hljs-built_in"><span class="hljs-built_in">NSString</span></span>*jpselectorname = [<span class="hljs-built_in"><span class="hljs-built_in">NSString</span></span>Stringwithformat:<span class="hljs-string"><span class="hljs-string">@ "[email protected]"</span></span>, selectorname]; SEL Jpselector =<span class="hljs-built_in"><span class="hljs-built_in">nsselectorfromstring</span></span>(jpselectorname);<span class="hljs-keyword"><span class="hljs-keyword">if</span></span>(!class_respondstoselector (object_getclass (slf), Jpselector)) { ... }<span class="hljs-built_in"><span class="hljs-built_in">Nsmutablearray</span></span>*arglist = [[<span class="hljs-built_in"><span class="hljs-built_in">Nsmutablearray</span></span>alloc] init]; [argList addobject:slf];<span class="hljs-keyword"><span class="hljs-keyword"></span> for</span>(<span class="hljs-built_in"><span class="hljs-built_in">Nsuinteger</span></span>i =<span class="hljs-number"><span class="hljs-number">2</span></span>; I < numberofarguments; I++) {...}<span class="hljs-comment"><span class="hljs-comment">//get parameters after invoke Jpsector invoke Jsfunction implementation</span></span> <span class="hljs-keyword"><span class="hljs-keyword">@synchronized</span></span>(_context) {_t<span class="hljs-built_in"><span class="hljs-built_in">mpinvocationarguments</span></span>= Formatoctojslist (argList); [invocation setselector:jpselector]; [invocation invoke]; _t<span class="hljs-built_in"><span class="hljs-built_in">mpinvocationarguments</span></span>=<span class="hljs-literal"><span class="hljs-literal">Nil</span></span>; } }</code></pre>Patch Site Recovery Supplement<p><p>Patch site recovery features are primarily used to continuously update scripts in the application Scenario. Because iOS app apps press the home key or the phone is interrupted, the app is actually first into the background runtime (applicationwillresignactive), and when we use the app again next time, If the background app is not terminated (applicationwillterminate), then the app does not go appliation:didfinishlaunchingwithoptions method, But will go (applicationwillenterforeground). For this scenario, if we update the online script continuously, then the second script update cannot retain the first method implementation, and the recovery of the field function will also help us to undo the ability of the online script to restore its own code.</p></p>On-site recovery of Jspatch<p><p>In this paper, on the basis of Jspatch added on-site recovery function; Source address reference:</p></p> <ul> <ul> <li>Jspatchdemo to increase site recovery:<br>Https://github.com/philonpang/JSPatch.git</li> </ul> </ul><p><p>The description is as Follows:</p></p><p><p>(1) added two start and end call functions in JPEngine.h as Follows:</p></p><pre class="hljs cs"><pre class="hljs cs"><code class="cs"> <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">js_start</span>(<span class="hljs-params">NSString* initScript</span>)</span>; <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">js_end</span>(<span class="hljs-params"></span>)</span>;</code></pre></pre><p><p>(2) the implementation of the calling function in JPENGINE.M and the modification of the partial code in the recovery field: mainly using the replacement method and the new method of the cache (_jsoveridemethods, mainly This)</p></p><pre class="hljs objectivec"><code class="objectivec"> <span class="hljs-comment"><span class="hljs-comment">//handling Replacement method, selector refers back to the original Imp,jpselector and Origselector both point to the non-implemented imp</span></span> <span class="hljs-keyword"><span class="hljs-keyword">if</span></span>([jpselectorname hasprefix:<span class="hljs-string"><span class="hljs-string">@ "_jp"</span></span>]){<span class="hljs-keyword"><span class="hljs-keyword">if</span></span>(class_getmethodimplementation (cls,<span class="hljs-keyword"><span class="hljs-keyword">@selector</span></span>(forwardinvocation:)) = = (IMP) Jpforwardinvocation) {SEL origforwardselector =<span class="hljs-keyword"><span class="hljs-keyword">@selector</span></span>(origforwardinvocation:); IMP origforwardimp = class_getmethodimplementation (cls, origforwardselector); Class_replacemethod (cls,<span class="hljs-keyword"><span class="hljs-keyword">@selector</span></span>(forwardinvocation:), origforwardimp,<span class="hljs-string"><span class="hljs-string">"[email protected]:@]</span></span>); Class_replacemethod (cls, origforwardselector, _objc_msgforward,<span class="hljs-string"><span class="hljs-string">"[email protected]:@]</span></span>); }<span class="hljs-built_in"><span class="hljs-built_in">NSString</span></span>*selectorname = [jpselectorname stringbyreplacingoccurrencesofstring:<span class="hljs-string"><span class="hljs-string">@ "_jp"</span></span>Withstring:<span class="hljs-string"><span class="hljs-string">@""</span></span>];<span class="hljs-built_in"><span class="hljs-built_in">NSString</span></span>*origselectorname = [jpselectorname stringbyreplacingoccurrencesofstring:<span class="hljs-string"><span class="hljs-string">@ "_jp"</span></span>Withstring:<span class="hljs-string"><span class="hljs-string">@ "ORIG"</span></span>]; SEL Jpselector =<span class="hljs-built_in"><span class="hljs-built_in">nsselectorfromstring</span></span>(jpselectorname); SEL selector =<span class="hljs-built_in"><span class="hljs-built_in">nsselectorfromstring</span></span>(selectorname); SEL Origselector =<span class="hljs-built_in"><span class="hljs-built_in">nsselectorfromstring</span></span>(origselectorname);<span class="hljs-keyword"><span class="hljs-keyword">if</span></span>(class_respondstoselector (cls, origselector) && class_respondstoselector (cls, selector) && Class_respondstoselector (cls, Jpselector)) {<span class="hljs-built_in"><span class="hljs-built_in">nsmethodsignature</span></span>*methodsignature = [cls instancemethodsignatureforselector:origselector]; method = Class_getinstancemethod (cls, origselector);<span class="hljs-keyword"><span class="hljs-keyword">Char</span></span>*typedescription = (<span class="hljs-keyword"><span class="hljs-keyword">Char</span></span>*) method_gettypeencoding (method); IMP forwardemptyimp = Getemptymsgforwardimp (typedescription, methodsignature); IMP origselectorimp = class_getmethodimplementation (cls, origselector); Class_replacemethod (cls, selector, origselectorimp, typedescription); Class_replacemethod (cls, jpselector, forwardemptyimp, typedescription); Class_replacemethod (cls, origselector, forwardemptyimp, typedescription); } }<span class="hljs-comment"><span class="hljs-comment">//new method for handling additions</span></span> <span class="hljs-keyword"><span class="hljs-keyword">Else</span></span>{isclsnew =<span class="hljs-literal"><span class="hljs-literal">YES</span></span>; SEL Jpselector =<span class="hljs-built_in"><span class="hljs-built_in">nsselectorfromstring</span></span>(jpselectorname);<span class="hljs-keyword"><span class="hljs-keyword">if</span></span>(class_respondstoselector (cls, Jpselector)) {<span class="hljs-built_in"><span class="hljs-built_in">nsmethodsignature</span></span>*methodsignature = [cls instancemethodsignatureforselector:jpselector]; method = Class_getinstancemethod (cls, jpselector);<span class="hljs-keyword"><span class="hljs-keyword">Char</span></span>*typedescription = (<span class="hljs-keyword"><span class="hljs-keyword">Char</span></span>*) method_gettypeencoding (method); IMP forwardemptyimp = Getemptymsgforwardimp (typedescription, methodsignature); Class_replacemethod (cls, jpselector, forwardemptyimp, typedescription); } }</code></pre>Those pits in Hotfixpatch.<p><p>Jspatch also encounters a lot of pits during use, although both frameworks are now able to add executable code, but applying them to developing functional components is not advisable. For example, I encountered a hole in the first use of jspatch:</p></p> <ul> <ul> <li><p>When the JS script overwrites the Optional Protocol method of an inherited class that is not implemented in the derived class, the JS patch method is not invoked TableView reload, but the TableView method that can invoke the substitution is explicitly called in selector In addition, if the protocol method is overridden in a derived class, it can be adjusted;</p></li> </ul> </ul><br><p><p>iOS hot Update-jspatch Implementation principle +patch onsite Recovery</p></p></span>
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.