IOS/Flutter dynamic conversation

Why do you need to be dynamic? In fact, operational needs are secondary, and fixing serious problems on the line is more important.

Does it have to be dynamic? Not necessarily, foreign developers seem to prefer better mechanisms to avoid problems, better CR/CI/ unit testing, etc., while domestic developers tend to be more dynamic.

This difference exists objectively and may be related to the way of thinking, technological development and even the market environment. We won’t go into that here, but as a domestic iOS developer, dynamic has to be a technical concern.


The iOS platform is unique when it comes to dynamic technology. Because it is the only platform that forbade you from delivering execution dynamic libraries at the system level, it only gives execution permissions to executables that come with the installation package, a limitation that cannot be circumvented at the APP level.

So other platforms simply replace the relevant executables. It’s even easier if you do a plug-in.

Fortunately, Objc is a more dynamic language, not as dynamic as scripting languages like JS, but it can still:

  • The runtime constructs classes and methods

  • Implementation of run-time replacement methods

This means that we can do many, many things that are very close to modifying programs arbitrarily and executing arbitrary logic: implementing new methods, which are implementations of concrete logic.

The easiest way to do this is to create an interpreter for a scripting language and call the interpreter in a new method to do the logic. There was an early Wax project, lua. But as iOS came with JSCore and the JS language was much more popular than Lua, JSPatch replaced Wax.

On the basis of this dynamic JS, more schemes are derived. One is RN/Weex, with all logic using JS and rendering using Native components. One type is small program, whose logic also uses JS. Rendering is currently a limited Native component of Web+, but it should be noted that the development specification of small program does not limit the specific implementation of the underlying rendering, and it can completely switch to other ways of rendering without perception in the future (some platforms have already tried).

This type of JS-BASED dynamic solution has some disadvantages:

  1. The cost of JS and native calling each other is relatively large. Therefore, RN/Weex has unavoidable performance bottlenecks in some scenarios.

  2. When working with JSPatch, some type conversions and memory management may also require attention, since the semantics of JS and Objc are inherently inconsistent.

  3. Native developers are not necessarily familiar with JS

Therefore, two sets of schemes are derived. One is didi, which allows developers to write Objc code, compile it into JS by tools, and then distribute it. In this way, the cost of business developers can be reduced. The other is Tencent mobile QQ, which implements an Objc interpreter to solve this problem.

The mobile QQ team’s radical dynamic scheme is called OCS, referring to OCS — the craziest iOS dynamic scheme in the history.

As mentioned earlier, Objc itself is dynamic, but the implementation of pure logic still needs a carrier, which is done by scripting language, while OCS has its own virtual machine to do. Of course, this virtual machine does not need to realize the complete ability to explain the execution of Objc. The process of code parsing and AST generation can be done offline, that is, the Patch code can be written and packaged by clang-based tools for delivery. The actual implementation of Objc can call the Runtime implementation directly, so all the VM really needs to implement is some simple C syntax. It actually looks pretty good. Performance has a significant advantage over JSPatch because cross-language overhead is avoided.

This performance advantage is not significant if it is a hot patch, so the main starting point of OCS may be to slim down the installation package and implement some functions through it, which is more demanding on performance.

This approach is similar to the OCEval- Dynamic Implementation of the ObjectiveC hot fix project. However, OCEval seems to include the parsing part in the VM. It is not perfect yet, but it is a good reference.


In general, Objc can do a lot of dynamic things because of the dynamic nature of the language, even though iOS officially doesn’t allow dynamic code execution. Swift, on the other hand, is a static language (leaving aside Swift’s use of the Objc Runtime, which is unlikely to restrict the entire project), so these ideas are almost impossible to use on Swift. Even if we were to build a complete Swift interpreter, it would be difficult to bridge over the original code.

I don’t know any good plan for Swift project. Improve your CR/CI process and improve your code quality.


Again, the dynamics of Flutter. Dart, as a static language, is also not very dynamic.

On other platforms, products can be directly replaced, just calculate a Diff and make a Patch. The idea is relatively simple, but iOS will not work, after all, Dart’s AOT products are executable machine code.

Xianyu provides a template resolution solution, which is basically to implement dynamic UI delivery, which can support the operation activities, and Hotfix is powerless.

The Tencent Watch team developed a MXFlutter solution that uses JS to write UI layer logic. JS logic can be replaced dynamically anyway. Conclusion first, this is a toy, hardly a landing point. If you think about the call path here, dart-Native JS two levels of cross-language calls, the whole UI layer does this, the performance is going to be poor; The Widget Tree is generated from the JS side, mapped to JSON, passed to Dart, and then parsed back to the Widget Tree. The performance cost is also quite high, and the declarative UI means that the build process must be called frequently. Ha ha ha ha forgive me not to smile.

But even if all else fails, we have a last resort: introduce the full DartVM at Release. This is basically releasing the Debug for Flutter, so that the Engine takes about 40M to install (including the Dart VM), and the Dart part can be delivered dynamically. The downside is that Dart’s JIT performance may not be as good as AOT’s, especially during startup. But I found a benchmark on the Internet, which looks not much worse or even many aspects of JIT better, refer to Dart vs Dart AOT.

The DartVM solution may be the ultimate solution for making Flutter dynamic.


Although theoretically c and other languages compiled directly to machine code are the real ceiling, in practice, vM-based languages are not much worse because they can get some runtime information and do some runtime compilation, and some scenarios are easier to optimize.

For example, Dart issue AOT code is 65% slower than JIT on dart_style benchmark which implies better JIT optimization of regular expressions.