我司iOS现有项目使用Objective-C开发,因为大量功能代码通过mPaaS平台运行的H5,所以并没有大量开发的业务逻辑和界面,只需要把宿主架构设计好,对H5的支持(插件)开发支援好,大多数情况下写的代码都在扩展框架。
但今年来用户量不断增加,我们对APP的体验也有了更高的要求,最主要的要求是提高界面丝滑度和流畅度及界面展示效率,以此提高用户的使用体验。但传统H5无论怎么优化,从根本上还是单线程的解释型运行原理,在界面复杂以及前端逻辑重的情况下,很难做到媲美原生交互体验。另外,一些界面过渡动画及特效无法做到,特别是共享元素动画,很难做到。
这种背景下,计划采用原生swiftUI进行主流程界面重构,但完全重写工作量巨大,所以采用独立模块的形式进行集成,逐步进行替代。
采用独立的库可以减少对主项目的依赖,完全解耦,在主项目同级别创建模块目录,使用pod创建.podspec文件。
上图,cclx-mpaas-gapp为主项目,gapp-quotation为独立模块库,然后引入主项目。
pod 'GappQuotation', :path => '/Users/hongbozhao/Source/iOS/gapp-quotation'
这时候执行pod install后,在主项目的Pods下,Development Pods中就有了刚才创建的组件库。在库里面创建QuotationMainView.swift文件,内容如
import SwiftUI
import SVGKit
struct QuotationMainView: View {
@ObservedObject var store = VoiceModel.shared
var closeWindowCallback: (() -> Void)?
var body: some View {
ZStack{
【此处省略】
}
.onTapGesture {
hideKeyboard()
}
}
}
接下来把此View嵌入即可。
在iOS开发中,通过UIHostingController把swiftUI的view嵌入传统UIView中,UIHostingController属性rootView赋值刚创建的swiftUI即可,然后把UIHostingController实例化的hostingMain添加到UIView中即可,如下。
let hostingMain = UIHostingController(
rootView: mainView
)
view.addSubview(hostingMain.view)
完整的部分代码如下
import UIKit
import SVGKit
import SwiftUI
class QuotationViewController: UIViewController {
var mainView = QuotationMainView()
override func viewDidLoad() {
super.viewDidLoad()
let hostingMain = UIHostingController(
rootView: mainView
)
hostingMain.view.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(hostingMain.view)
NSLayoutConstraint.activate([
hostingMain.view.topAnchor.constraint(equalTo: view.topAnchor),
hostingMain.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
hostingMain.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
hostingMain.view.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
}
}
由于主项目使用OC开发,ViewController不能直接被调用,需要用@objc进行声明,这里专门写个继承NSObject的帮助类供主项目OC
调用。如下
@objcMembers
public class QuotationHelper : NSObject{
public static let shared = QuotationHelper()
private override init() {
}
public func startQuotation(vc:UIViewController, data:NSDictionary) -> Bool {
let quotatioVC = QuotationViewController()
quotatioVC.fromData = data.object(forKey: "data") as? String
vc.present(quotatioVC, animated: true)
return true
}
}
此处需要注意的是,类必须继承NSObject,添加@objcMembers头对成员进行开放,写成单例为了内外部公用。主项目OC只需要调用帮助类的start即可打开模块的ViewController界面。
QuotationHelper *helper = [QuotationHelper shared];
[helper startQuotationWithVc:context.currentViewController data:data];
至此,整个过程已经完全跑通。
在开发此功能模块的过程中,使用swiftUI写了界面、swift写了业务逻辑及api数据请求。在开发Android平台同样功能的时候,用kotlin写了业务逻辑及api数据请求,用Jetpack Compose写了Android界面。
总有一种感觉,同样的时间过了2遍,对工作来说是一种资源浪费,对个人的时间来说也是另一种不尊重。
于是对这种情况进行了思考改变,经过充分调研,决定未来尝试用KMP(Kotlin Multiplatform)提高效率。
个人已经成功进行了尝试,也已把经验在我的其他文章中进行了分享(作者主页查找),为有同样思考的人提供一种可能。