iOS App移植到Unix上的工作量分析

目的

我试图将iOS App移植到Unix系统。在作者持有源码的前提下,合法地帮助作者将源码编译并运行。我毫不犹豫地选择激进地支持最新版iOS项目设计,以抛弃老旧的Objective-C和StoryBoard支持。

LaunchScreen

通过解析plist文件,读取UILaunchStoryboardName,可确定LaunchScreen文件名。plist文件是Apple继承自BSD的文件格式,其类似XML的格式没有解析难度。

暂时,LaunchScreen依然使用了StoryBoard。 我相信它很快会被SwiftUI取代,于是决定跳过LaunchScreen的实现。

加载UI

info.plist中,UISceneDelegateClassName负责指定UISceneDelegate的类名。默认为$(PRODUCT_MODULE_NAME).SceneDelegate。此处需要留意项目开发中module的概念,不要误以为是指定文件名。

SceneDelegate

UIWindowSceneDelegate负责iOS App的UI绘制。首先导入的UIKit与SwiftUI都是闭源组件,移植到Unix中必然需要我来实现。

import UIKit
import SwiftUI

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
        ...
}

UIKit

CoreGraphics提供2D图形绘制能力,如绘制一个形状,颜色等。UIKit上CoreGraphics之上,提供了绘制按钮,图片,列表,导航栏,工具栏等复杂组件的能力。想要实现UIKit,必须先搞定CoreGraphics。

CoreGraphics

The Core Graphics framework is based on the Quartz advanced drawing engine. It provides low-level, lightweight 2D rendering with unmatched output fidelity. You use this framework to handle path-based drawing, transformations, color management, offscreen rendering, patterns, gradients and shadings, image data management, image creation, and image masking, as well as PDF document creation, display, and parsing.

In macOS, Core Graphics also includes services for working with display hardware, low-level user input events, and the windowing system.

从功能来看,CoreGraphic可以对标Wayland。此处我不再细分CoreGraphics与Quartz之间的关系,因为底层实现的差异会被Display Server层掩盖。

SwiftUI

SwiftUI的实现需要分为语法解析和实现两部分。语法解析可以参考Flutter,问题不大。实现部分,SwiftUI继承自UIKit,但加入了Scene的概念用于生命周期管理,也不会是个大问题。

UIHostingController

在scene的willConnectTo session回调中,通过指定self.window.windowScene.rootViewController.rootView为ContentView,完成rootView的绘制。这里很有意思的是,传入的ContentView是个结构体。既然View是个结构体,一切都好办了。它无论如何跳不出Swift语言的Struct语法。

        // Use a UIHostingController as window root view controller
        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(rootView: ContentView())
            self.window = window
            window.makeKeyAndVisible()
        }

IDE

最难的还是IDE实现。我试图改造IntelliJ社区版,以完成IDE定制的工作。如何将UI逻辑与Wayland对接,如何完成热加载实时渲染,都是巨大的挑战。首先,IntelliJ社区版不支持C-like语言,其CLion与AppCode都是闭源商业的。我需要完成一个结合CLion与AppCode的Unix版插件,才能实现Swift on Unix功能。然后,我需要将SwiftUI功能集成到社区版中,增加大量功能,实现最新版Xcode的功能。最后,考虑到iOS App的生命周期,我需要将其运行在沙盒中来模拟其生命周期。

结论

可行。工作量极大。一个人做非常困难,但并非不可能。

Publish At: Author:Aiden Leong

Read more posts by this author

comments powered by Disqus