Bo2SS

Bo2SS

2 Application Development (Part 1)

It's been a while since we explored "The Complete Overview of iOS Knowledge System." Now, we begin a new chapter—Application Development. In this chapter, we will discuss GUI frameworks, reactive frameworks, animations, A/B testing, and message buses in iOS development.

image

Previous Recommendations:

If you missed the first chapter—Fundamentals, you can jump to it here:

《The Complete Overview of iOS Knowledge System》Fundamentals (Part 1)

《The Complete Overview of iOS Knowledge System》Fundamentals (Part 2)

《The Complete Overview of iOS Knowledge System》Fundamentals (Part 3)

《The Complete Overview of iOS Knowledge System》Fundamentals (Best Learning Path)

21 | What GUI frameworks can be used for iOS development besides Cocoa?#

To optimize the app's startup speed, in addition to addressing the main thread, we can also consider optimizations on the GUI (Graphical User Interface).

The currently popular GUI frameworks besides Cocoa Touch include Texture (formerly AsyncDisplayKit), WebKit, React Native (Facebook), and Flutter (Google). Their comparisons are as follows:

GUI FrameworkCocoa TouchTextureWebKitReact NativeFlutter
Platform supportiOSiOSiOS, AndroidiOS, AndroidiOS, Android
Programming languageOC, SwiftOC, SwiftJavaScriptJavaScriptDart
Render engineCoreAnimationCoreAnimationWebCoreNativeSkia
Layout methodFrame, Auto LayoutFlexBoxFrame, FlexBoxFrame, FlexBoxFrame, FlexBox, LayoutWidgets
  • FlexBox layout allows iOS developers to utilize advanced W3C standard responsive layouts. The newly introduced UIStackView layout method in iOS is also designed based on the FlexBox layout concept. Cocoa Touch framework itself does not support FlexBox layout, but it can be used through Facebook's Yoga library.

  • The basic unit of the Texture framework is the ASDisplayNode, which is an abstraction based on UIView. Compared to UIView, ASDisplayNode is thread-safe, allowing the entire hierarchy to be instantiated and configured in parallel on a background thread. Because Texture uses asynchronous node calculations, it can improve the responsiveness of the main thread.

  • In iOS development, the UIWebView and WKWebView controls we most commonly use are based on the WebKit framework. The author has previously written a blog post titled “In-Depth Analysis of WebKit” that analyzes its principles in detail.

  • The rendering-related introductions of React Native and Flutter frameworks will be detailed in the upcoming section on native and frontend collaboration.

What is in a GUI Framework?#

Controls, render trees, render layer trees.

  • Controls are primarily responsible for storing and updating the data of interface elements;

  • The render tree is an abstract tree structure that mainly records the relationships between controls;

  • The render layer tree consists of render layer objects, which are created based on the optimization conditions of the GUI framework. It records which controls are included, and combined with the render tree layout, it can generate a Bitmap, which is ultimately rendered by the GPU.

The relationship diagram among them is as follows:

Relationship among controls, render trees, and render layer trees—《Geek Time》

Others:

  • The slow display of web pages using WebKit is not due to its rendering performance being inferior to other frameworks, but mainly due to the way CSS and JavaScript resources are loaded. Additionally, compatibility with older versions during HTML, CSS, and JavaScript parsing, JavaScript type inference failures requiring reprocessing, and the lack of a reuse mechanism for lists also contribute to the overall performance of the WebKit framework being less favorable than other frameworks.

  • Flutter was originally based on the Chrome browser engine. Later, considering Flutter's performance, Google removed its support for HTML, CSS, and JavaScript, opting for its own Dart language to shed historical burdens. Specific details can be found in the interview video with Flutter founder Eric—Zhihu.

Rendering Process#

The rendering technology in GUI frameworks has remained stable, generally going through three stages: layout, rendering, and composition.

  • Layout stage: Mainly calculates the size and position of controls based on the render tree.

  • Rendering stage: Primarily utilizes graphic functions to compute the content of the interface. Generally, 2D rendering is computed using the CPU, while 3D rendering will use the GPU.

  • Composition stage: Mainly merges layers to save display memory.

Asynchronous Drawing of Nodes in Texture:

For iOS developers looking to significantly enhance user interaction experiences, Texture offers a low switching cost and substantial performance gains.

Its advantages include:

  1. Development of thread-safe ASDisplayNode;

  2. Good coexistence with UIView.

Asynchronous drawing principle:

ASDisplayLayer (a wrapper for CALayer) is the starting point for all drawing. Drawing events are first set in the displayBlock, and then ASDisplayNode (which replaces the delegate in CALayer) calls the displayBlock for asynchronous drawing. Since the displayBlock uses thread-safe Core Graphics, it can be executed asynchronously on a background thread.

22 | A Detailed Look at the Evolution of iOS Reactive Frameworks#

Introduction to Reactive Frameworks#

Definition: Frameworks that support the reactive programming paradigm.

Characteristics: By using reactive frameworks, changes in data can be propagated using data streams during programming. The computational model responding to this data stream will automatically compute new values and pass them to the next responsive computational model through the data stream, and so on, until there are no more responders.

Current Status: iOS reactive frameworks include ReactiveCocoa (abbreviated as RAC) and RxSwift, but neither has gained popularity until the advent of React.js in the frontend, which spread the reactive approach widely.

So, why hasn't ReactiveCocoa gained traction in native iOS development?

Let's Explore the Question#

The concept of the ReactiveCocoa framework is fundamentally consistent with that of React.js. So, let's see what the React.js framework has done. The key lies in the addition of the Virtual Document Object Model (Virtual DOM).

At the core of the React.js framework is a Virtual DOM, which is bound to the state of page components and has a mapping and transformation relationship with the DOM (Document Object Model). Its rendering principle is illustrated in the following diagram:

Rendering Principle of React.js Framework—《Geek Time》

It can be seen that:

  • The React.js framework first operates on the Virtual DOM, which does not directly render the DOM. Instead, after completing the Diff calculation to obtain all actual changed nodes, it performs a DOM operation and then renders the entire structure. The Virtual DOM acts as a cache between JavaScript and the DOM.

  • Unlike JavaScript, which re-renders the entire DOM every time it operates, resulting in significant performance loss.


Returning to the question: Why hasn't ReactiveCocoa gained traction in native iOS development?

For the frontend, the structure of the DOM tree is very complex, and a complete change to the DOM tree can lead to severe performance issues, which the Virtual DOM can effectively address.

However, for iOS native Cocoa Touch framework:

  • This performance issue does not exist, as its interface node tree structure is much simpler than the DOM tree;

  • Moreover, its rendering mechanism differs from that of the frontend. Cocoa Touch does not immediately re-render the entire view node tree when updating the view. Instead, it marks the view as needing a layout through the setNeedsLayout method, and only when the drawing cycle reaches this view node does it call the layoutSubviews method for re-layout, followed by rendering.

Thus, the ReactiveCocoa framework has not brought better performance to iOS apps. When a framework is optional and does not provide significant benefits, teams generally have no reason to adopt it.


Others: There are many aspects of ReactiveCocoa worth learning from, such as:

  • Upper-level interface design philosophy: Functional reactive programming can be implemented through callbacks and KVO;

  • Use of macros: Refer to Reactive Cocoa Tutorial: Amazing Macros——sunnyxx.

23 | How to Create Stunning Animation Effects?#

Industry Pain Points#

  • Manually writing animation code is very complex, and many animation detail adjustments require constant communication and refinement with animation designers;

  • Developers across iOS, Android, and Web platforms need to maintain separate animation code.

The question arises: Is there a way to isolate animation production from programming development, allowing specialists to focus on their tasks while maintaining consistent animation effects across platforms?

Lottie#

Yes, that would be the Lottie framework, an animation framework open-sourced by Airbnb.

Usage Steps:

  1. Animation designers create animations using After Effects and then export the animations as JSON files using the Bodymovin plugin;

  2. Developers use Lottie to load and render this JSON file, automatically converting it into the corresponding animation code.


Implementation Principle:

What Lottie does in iOS is:

  1. It maps the contents of the JSON file (the intermediate medium generated by After Effects) to the properties of classes like LayerModel, Keyframe, ShapeItem, DashElement, Marker, Mask, and Transform in iOS, saving them;

  2. It then renders through CoreAnimation.

Thus, Lottie automates the process of converting animation design files into development code, delegating the task of setting properties like LayerModel to the JSON file and Lottie mapping rules.


💡Tips:

  1. A workflow like Lottie may be the future trend, just as the current development trend in iOS indicates that more and more business logic no longer needs to be implemented entirely in Objective-C or Swift, but can be described using JavaScript or DSL, or even tools, and then converted into an intermediate code like JSON. Different platforms can then parse and process the same intermediate code to execute the business logic described by it.

  2. For detailed explanations and usage examples of Lottie, refer to the Lottie Official iOS Tutorial. Lottie supports not only physical effects but also transition animations between pages.

  3. Developers without the cooperation of animation designers can check out LottieFiles, a platform where animation designers share their works, and every animation effect's JSON file is available for download.

Author: Okiri George

24 | A/B Testing: A Powerful Tool for Validating Decision Effects#

Definition of A/B Testing#

A/B testing, also known as bucket testing or split testing, refers to testing two versions, A and B, of a variable to observe different user reactions and determine which version is more effective, similar to the two-sample hypothesis testing used in statistics.

In simple terms, A/B testing checks which version of a feature yields the best user feedback among different app users.

A/B Testing in App Development:

In the iteration of app versions, we can understand the old version as version A in A/B testing and the new version as version B. Both versions coexist, with version B initially placing a small portion of users in the B testing bucket, gradually expanding the user base, and analyzing the data from versions A and B to see which version is closer to the desired goal, ultimately determining which version to use.

Overall, A/B testing is a data-driven, reversible gray scheme that is objective, safe, and low-risk, serving as a mature trial-and-error mechanism.

A/B Testing Framework Design#

An A/B testing framework mainly consists of three parts, as illustrated in the structure diagram below:

Structure Diagram of A/B Testing Scheme—《Geek Time》

  • Strategy service, which provides strategies for decision-makers, including decision-making processes and strategy dimensions.

    • Generally provided by the server, allowing it to allocate testing buckets based on the distribution of user groups at any time.
  • A/B testing SDK, integrated into the client, used to control the upper-level business to follow different strategies.

    • Recommended: SkyLab, authored by Mattt, who is also known for the AFNetworking and Alamofire libraries. This library uses blocks to handle the differences between A/B versions in its interface design, making it highly usable and worth learning.

    • Activation mechanism: If a strategy is only effective in one place, a hot start activation mechanism can be used; if a strategy is effective in multiple places, it is better to use a cold start activation mechanism.

  • Logging system, responsible for feedback on strategy results for analysts to analyze the outcomes of different strategy executions.

    • Generally provided by the server.

25 | How to Build a Bottom-Level Publish and Subscribe Event Bus?#

Definition of Event Bus#

An event bus is an implementation of the publish and subscribe design pattern, which decouples one-to-one and one-to-many relationships between components through publishing and subscribing.

This design pattern is particularly suitable for the data layer to inform the UI layer subscribers of data asynchronously, allowing the UI layer and data layer to remain uncoupled, so that changes in the data layer or UI layer do not affect the business layer.

  • Block and Delegate. Suitable only for one-to-one patterns; if continuous asynchronous publishing to the next data subscriber is needed (where messages have causal relationships), callback nesting can occur.

  • KVO and NSNotificationCenter. They support one-to-many patterns. However, KVO is strongly dependent on properties; as soon as a property is updated, it will publish to all observers, leading to overly flexible corresponding relationships that are difficult to manage and maintain. NSNotificationCenter faces similar issues, maintaining relationships between publishers and subscribers through strings, which not only lacks readability but also suffers from the same management and maintenance difficulties as KVO.


Q: Are there any good third-party libraries to handle event buses?

Actually, the previously mentioned reactive third-party libraries ReactiveCocoa and RxSwift have no issues supporting event buses, but these two libraries focus more on reactive programming, with event buses being just a small part of them. Therefore, using them for this purpose may be overkill.

Currently, there is a pattern in the frontend field called Promise, which is a unified rule set specifically designed for asynchronous data operations.

Promise#

Essentially, this pattern uses Promise objects to hold asynchronous data operations, while providing a unified interface for handling asynchronous data operation events.

Promise objects have three states:

  1. pending: The asynchronous event is waiting to be processed;

  2. fulfilled: The asynchronous event has successfully completed;

  3. rejected: The asynchronous event has not successfully completed.


There are also two important methods: then and catch.

Every time a Promise object executes the then or catch method, it returns the previous Promise object, and the state of that Promise object changes based on the result of the asynchronous operation.

  • then: Executes the then method corresponding to the subscription operation, triggering the corresponding publishing operation of the Promise object. The then method returns the Promise object and can continue to execute multiple then methods synchronously, thus achieving one publishing operation corresponding to multiple subscription events.

  • catch: If the Promise object returned after executing the then method is in the rejected state, the program will directly execute the catch method.


Q: How to use the Promise pattern in iOS?

Introduce PromiseKit (developed by Max Howell, the author of Homebrew).

Additionally, PromiseKit provides extensions for Apple's APIs, such as UIKit, Foundation, CoreLocation, QuartzCore, CloudKit, etc., and even supports third-party frameworks like Alamofire. For specifics, refer to PromiseKit Organization.

By using a simple, clear, and standardized Promise interface to connect asynchronous data retrieval, business logic, and interfaces, future maintenance or refactoring will be much easier. Give it a try!

That's all for today's sharing! Next time, we will enter the second part of "The Complete Overview of iOS Knowledge System" on Application Development, covering topics such as JSON processing, layout frameworks, rich text, TDD/BDD, and coding standards. Don't forget to follow along, and see you next time!

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.