SwiftUI嵌入ViewController

一、背景说明

我司iOS现有项目使用Objective-C开发,因为大量功能代码通过mPaaS平台运行的H5,所以并没有大量开发的业务逻辑和界面,只需要把宿主架构设计好,对H5的支持(插件)开发支援好,大多数情况下写的代码都在扩展框架。

但今年来用户量不断增加,我们对APP的体验也有了更高的要求,最主要的要求是提高界面丝滑度和流畅度及界面展示效率,以此提高用户的使用体验。但传统H5无论怎么优化,从根本上还是单线程的解释型运行原理,在界面复杂以及前端逻辑重的情况下,很难做到媲美原生交互体验。另外,一些界面过渡动画及特效无法做到,特别是共享元素动画,很难做到。

这种背景下,计划采用原生swiftUI进行主流程界面重构,但完全重写工作量巨大,所以采用独立模块的形式进行集成,逐步进行替代。

二、嵌入过程

2.1 swiftUI界面开发

SwiftUI嵌入ViewController_第1张图片

采用独立的库可以减少对主项目的依赖,完全解耦,在主项目同级别创建模块目录,使用pod创建.podspec文件。

SwiftUI嵌入ViewController_第2张图片

上图,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嵌入即可。

2.2 嵌入过程

在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)
        ])
    }
}

2.3 OC界面调用

由于主项目使用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)提高效率。

怎么进行操作?

个人已经成功进行了尝试,也已把经验在我的其他文章中进行了分享(作者主页查找),为有同样思考的人提供一种可能。

你可能感兴趣的:(swiftui,cocoa,ios)