IOS dynamic hotfix

Warnning

Purely technical sharing, welcome to Github like. https://github.com/dKingbin/DynamicOCCopy the code

preface

IOS hotfixes were also put on hold after the JSPatch incident. Bang God mentioned in “JSPatch — Dynamic Update of iOS APP” that in order to comply with Apple’s rules, the executable code cannot be dynamically issued as mentioned in 3.3.2 of “Apple Developer Program License Agreement”. JSPatch specifically around the JS circle, so as to achieve the curve to save the country, to achieve the hot update scheme. However, it turns out that Apple doesn’t approve of this solution either, and the fundamental reason is that JSPath goes too far in supporting most OC/C syntax.

thinking

Now that JSPatch’s detour from JS has been rejected by Apple, it’s time to go back to square one and start again. I think there is at least one sufficient condition for a new framework or new scheme, but it should not be too extreme. As objective-C is a dynamic language, it is normal to be able to dynamically execute all OC syntax, and frameworks like Aspects are approved by Apple. Whether you need to run all C functions is debatable. The second is to abandon javascript/ Lua and similar languages as updated scripts in favor of native Objective-C as the updated scripting language.

Run C functions dynamically

C language has no reflection mechanism. As a compiled language, machine code is generated during compilation. So if you want to get a pointer to a function from a string, there are roughly two methods:

  • Create a mapping table, the function name and function pointer to create a mapping table.
  • Dlsym, according to the dynamic link library operation handle and symbol, return the corresponding symbol address.

The second approach is the one currently being adopted by JSPatch and is, of course, being warned by Apple. Dlsym is very powerful and is the optimal solution for getting Pointers to functions. The first is very limited, but does not use dark magic.

Adopt Objective-C as the updated scripting language

Direct parsing of Objective-C syntax via Flex/yACC, no scripting languages like JS/Lua.

DynamicOC

As a result of this thinking, I recently worked on DynamicOC in my spare time, which has 100% native support for using Objective-C as the updated scripting language. Of course, running C functions dynamically still uses dlSYM to obtain function Pointers, which will gradually change to the mapping table.

The principle of

DynamicOC uses Flex/yACC for lexical analysis and syntax analysis, and is converted into a syntax spanning tree AST. The corresponding code is then executed by parsing each node. Because you use Objective-C as the scripting language, it’s easy to adapt.

Functional features

  • Execute OC code dynamically
  • Dynamically execute C functions and block asynchronous calls
  • Dynamically adding properties
  • Dynamic substitution method
  • Dynamic addition method
  • There are good unit tests
  • Flex/yACC implements a powerful OC syntax parser
  • Support CGRect/CGSize/CGPoint/NSRange/UIEdgeInsets/CGAffineTransform structure commonly used…

Basic usage

Dynamically executing blocks

NSString* text = @" \ __block int result = 0; \ UIView* view = [[UIView alloc]init]; \ void(^blk)(int value) = ^(int value){\ view.tag = value; The \}; \ blk(1024); \ return view.tag;";

ASTNode* root = [ASTUtil parseString:text];
ASTVariable* result = [root execute];
NSAssert([result.value doubleValue] == 1024, nil);
Copy the code

Dynamically execute C functions

int echo(int value) {
return value;
}

NSString* text = @" \
[OCCfuntionHelper defineCFunction:@\"echo\" types:@\"int, int\"]; \
return echo(1024);";

ASTNode* root = [ASTUtil parseString:text];
ASTVariable* result = [root execute];
NSAssert([result.value doubleValue] == 1024, nil);
Copy the code

Dynamically adding Property

NSString* text = @" \ [OCCfuntionHelper defineCFunction:@\"objc_setAssociatedObject\" types:@\"void,id,void *,id,unsigned int\"]; \ [OCCfuntionHelper defineCFunction:@\"objc_getAssociatedObject\" types:@\"id,id,void *\"]; \ NSString* key = @\"key\"; \ objc_setAssociatedObject(self, key, @(1024), 1); \ return objc_getAssociatedObject(self, key);";

ASTNode* root = [ASTUtil parseString:text];
ASTVariable* result = [root execute];
NSAssert([result.value doubleValue] == 1024, nil);
Copy the code

Supported syntax

  • if/else while do/while for
  • return break continue
  • i++ i– ++i –i
  • +i -i ! i
  • + – * / % and other four operations
  • > > < < & | ^ allelic operations
  • && | | > = < =! = > < and so on
  • ? :
  • __block
  • array[i] dict[@””]
  • @ 666 @ () @ @ [] {}
  • self super
  • self.property
  • self->_property
  • most of objective-c keyword

TODO

  • @available()
  • [NSString stringWithFormat:”%d”,value] : use [NSString stringWithFormat:”%@”,@(value)] instead.
  • dispatch_async / dispatch_after …
  • *stop =YES, in block
  • fix bugs

Github link here: DynmaicOC, feel helpful can click a star oh! Thank you very much!

Refer to the link

JSPatch — Dynamically update iOS apps

The story of iOS dynamics

Apple Developer Program License Agreement

Didi iOS DynamicCocoa was born and set sail