kuiklyui core-ksp ios

KuiklyUI 框架对 iOS 平台的泛化设计

1. iOS 平台泛化概述

KuiklyUI 框架通过抽象基类与平台特定实现相结合的方式,实现了对 iOS 平台的深度适配。iOS 平台的实现主要体现在 IOSTargetEntryBuilderIOSMultiTargetEntryBuilder 两个核心类中,它们共同构建了一套高效的跨平台桥接机制,使 Kotlin 代码能够与 iOS 原生代码无缝通信。

iOS 平台的泛化设计具有以下特点:

  • 采用典型的 iOS 委托模式(Delegate Pattern)实现跨语言调用
  • 基于 Kotlin/Native 技术实现与 Objective-C/Swift 的互操作
  • 支持灵活的单模块和多模块架构
  • 完整的异常捕获和处理机制

2. 核心实现类分析

2.1 IOSTargetEntryBuilder - 基础平台实现

IOSTargetEntryBuilder 是 iOS 平台的基础实现类,负责生成单模块场景下的核心桥接代码:

kotlin:/Users/hfq/codes/KuiklyUI/core-ksp/src/main/kotlin/impl/IOSTargetEntryBuilder.kt 复制代码
open class IOSTargetEntryBuilder : KuiklyCoreAbsEntryBuilder() {
    override fun build(builder: FileSpec.Builder, pagesAnnotations: List<PageInfo>) {
        builder.addType(
            TypeSpec.classBuilder(entryFileName())
                .addProperty(createDelegateProperty())
                .addProperty(createHadRegisterNativeBridgeProperty())
                .addFunction(createCallKtMethodFuncSpec(pagesAnnotations))
                .addType(createDelegateTypeSpec())
                .addType(createCompanionObject(pagesAnnotations))
                .build()
        )
    }
    
    override fun entryFileName(): String { return "KuiklyCoreEntry" }
    override fun packageName(): String { return "" }
    
    // 其他私有方法...
}

该类的核心职责是:

  • 构建 KuiklyCoreEntry 类,作为 Kotlin 与 iOS 原生代码通信的桥梁
  • 定义 Delegate 接口,由 iOS 原生代码实现以处理 Kotlin 到原生的调用
  • 实现页面注册和方法调用的核心逻辑
  • 提供异常捕获和处理机制

2.2 IOSMultiTargetEntryBuilder - 多模块支持实现

IOSMultiTargetEntryBuilder 扩展了基础实现,提供了 iOS 平台的多模块支持:

kotlin:/Users/hfq/codes/KuiklyUI/core-ksp/src/main/kotlin/impl/submodule/IOSMultiTargetEntryBuilder.kt 复制代码
class IOSMultiTargetEntryBuilder(
    private val isMainModule: Boolean, 
    private val subModules: String, 
    private val moduleId: String
) : IOSTargetEntryBuilder() {
    
    override fun build(builder: FileSpec.Builder, pagesAnnotations: List<PageInfo>) {
        if (!isMainModule) {
            // 子模块:创建单例对象
            builder.addType(
                TypeSpec.objectBuilder(entryFileName() + "_" + moduleId)
                    .addFunction(createSubModuleRegisterPagesFuncSpec(pagesAnnotations))
                    .build()
            )
        } else {
            // 主模块:创建完整的核心入口类
            builder.addType(
                TypeSpec.classBuilder(entryFileName())
                        .addProperty(createDelegateProperty())
                        // ... 其他属性和方法
                        .build()
            )
        }
    }
    
    // 其他方法...
}

该类通过构造参数控制生成不同类型的代码:

  • isMainModule:标识是否为主模块
  • subModules:主模块包含的子模块列表,用 & 分隔
  • moduleId:当前模块的唯一标识

3. 关键功能实现分析

3.1 委托模式实现

iOS 平台采用典型的委托模式实现 Kotlin 到原生的调用,核心是通过 createDelegatePropertycreateDelegateTypeSpec 方法:

kotlin 复制代码
fun createDelegateProperty(): PropertySpec {
    return PropertySpec.builder(
        VAR_NAME_DELEGATE, // "hrCoreDelegate"
        ClassName("", HR_CORE_ENTRY_DELEGATE).copy(true) // "Delegate?"
    )
        .mutable()
        .initializer("null")
        .build()
}

fun createDelegateTypeSpec(): TypeSpec {
    return TypeSpec.interfaceBuilder(HR_CORE_ENTRY_DELEGATE) // "Delegate"
        .addFunction(
            FunSpec.builder(AndroidTargetEntryBuilder.FUNC_NAME_CALL_NATIVE) // "callNative"
                .addParameters(createKtMethodParameters())
                .addModifiers(KModifier.ABSTRACT)
                .returns(Any::class.asTypeName().copy(nullable = true))
                .build()
        )
        .build()
}

这种设计允许 iOS 原生代码通过实现 Delegate 接口,并将其赋值给 hrCoreDelegate 属性,从而接收来自 Kotlin 的调用。

3.2 方法调用与注册机制

createCallKtMethodFuncSpec 方法是整个桥接机制的核心,负责处理从原生到 Kotlin 的方法调用:

kotlin 复制代码
fun createCallKtMethodFuncSpec(pagesAnnotations: List<PageInfo>): FunSpec {
    return FunSpec.builder(FUNC_NAME_CALL_KT_METHOD)
        .addParameters(createKtMethodParameters()) // 方法ID和6个参数
        .addStatement("try {")
        // 初始化和页面注册
        .addStatement("if (!BridgeManager.isDidInit()) {\n" +
                "BridgeManager.init()\n")
        .addStatement("$METHOD_NAME_TRIGGER_REGISTER_PAGES()") // "triggerRegisterPages()"
        .addStatement("}\n")
        // 注册NativeBridge
        .addStatement("        if (!hadRegisterNativeBridge) {\n" +
                "            hadRegisterNativeBridge = true\n" +
                "            val nativeBridge = NativeBridge()\n" +
                "            nativeBridge.iosNativeBridgeDelegate = object : NativeBridge.IOSNativeBridgeDelegate {\n" +
                "                override fun callNative(...) {\n" +
                "                    return hrCoreDelegate?.callNative(...)\n" +
                "                }\n" +
                "            }\n" +
                "            BridgeManager.registerNativeBridge(arg0 as String, nativeBridge)\n" +
                "        }")
        // 调用Kotlin方法
        .addStatement("BridgeManager.callKotlinMethod(methodId, arg0, arg1, arg2, arg3, arg4, arg5)")
        // 异常处理
        .addStatement("}")
        .addStatement("catch(t: Throwable) {")
        .addStatement("BridgeManager.callExceptionMethod(t.stackTraceToString())")
        .addStatement("}")
        .build()
}

该方法实现了以下关键功能:

  1. 首次调用时初始化 BridgeManager 并注册页面路由
  2. 创建并注册 NativeBridge 实例,设置 iOSNativeBridgeDelegate
  3. 委托实现将 Kotlin 对原生的调用转发给 iOS 实现的 Delegate
  4. 完整的异常捕获和处理机制

3.3 页面注册与检查

createCompanionObject 方法创建了伴生对象,提供页面注册和检查功能:

kotlin 复制代码
private fun createCompanionObject(pagesAnnotations: List<PageInfo>): TypeSpec {
    return TypeSpec.companionObjectBuilder()
        .addProperty(
            PropertySpec.builder(PROP_NAME_HAD_REGISTER_PAGES, Boolean::class.asTypeName())
                .mutable(true)
                .addModifiers(KModifier.PRIVATE)
                .initializer("false")
                .build()
        )
        .addFunction(
            FunSpec.builder(METHOD_NAME_PAGE_EXIST)
                .addParameter(ParameterSpec.builder(PARAM_NAME_PAGE_NAME, String::class.asTypeName()).build())
                .addStatement("$METHOD_NAME_TRIGGER_REGISTER_PAGES()")
                .addStatement("return BridgeManager.$METHOD_NAME_PAGE_EXIST($PARAM_NAME_PAGE_NAME)")
                .returns(Boolean::class.asTypeName())
                .build()
        )
        .addFunction(
            FunSpec.builder(METHOD_NAME_TRIGGER_REGISTER_PAGES)
                .addModifiers(KModifier.PRIVATE)
                .addStatement("if(!$PROP_NAME_HAD_REGISTER_PAGES) {")
                .addRegisterPageRouteStatement(pagesAnnotations)
                .addStatement("$PROP_NAME_HAD_REGISTER_PAGES=true")
                .addStatement("}")
                .build()
        )
        .build()
}

该伴生对象的主要功能:

  • 通过 triggerRegisterPages 方法注册所有页面路由
  • 通过 isPageExist 方法检查指定页面是否存在
  • 使用 hadRegisterPages 标志确保页面只注册一次

3.4 多模块支持机制

多模块支持是 iOS 平台实现的重要特性,通过 createSubModuleRegisterPagesFuncSpecaddSubModuleStatement 方法实现:

kotlin 复制代码
private fun createSubModuleRegisterPagesFuncSpec(pagesAnnotations: List<PageInfo>): FunSpec {
    return FunSpec.builder("triggerRegisterPages")
            .addRegisterPageRouteStatement(pagesAnnotations)
            .addSubModuleStatement()
            .build()
}

private fun FunSpec.Builder.addSubModuleStatement(): FunSpec.Builder {
    subModules.split("&").forEach { moduleName ->
        val name = moduleName.trim()
        if(name.isNotEmpty()) {
            addStatement(entryFileName() + "_" + name + ".triggerRegisterPages()")
        }
    }
    return this
}

多模块机制的工作原理:

  1. 主模块通过 subModules 参数指定所有子模块,以 & 分隔
  2. 主模块在初始化时,通过 addSubModuleStatement 方法调用所有子模块的 triggerRegisterPages 方法
  3. 每个子模块生成名为 KuiklyCoreEntry_${moduleId} 的单例对象,只负责注册自己的页面路由

4. 平台特性适配

iOS 平台的泛化设计充分考虑了其独特的技术特性:

4.1 委托模式的应用

iOS 开发中广泛使用委托模式(Delegate Pattern),KuiklyUI 框架在 iOS 平台的实现也遵循了这一设计模式:

  • 通过 hrCoreDelegate 属性接收 iOS 原生代码设置的委托对象
  • 定义 Delegate 接口规范原生代码需要实现的方法
  • 使用 iosNativeBridgeDelegate 处理反向调用

这种设计使得 Kotlin 代码能够无缝集成到 iOS 开发环境中,符合 iOS 开发者的习惯。

4.2 单例对象的使用

在多模块场景下,子模块生成的是单例对象而非类:

kotlin 复制代码
TypeSpec.objectBuilder(entryFileName() + "_" + moduleId)
    .addFunction(createSubModuleRegisterPagesFuncSpec(pagesAnnotations))
    .build()

这一设计简化了子模块的访问方式,无需创建实例即可调用其方法,符合 Kotlin/Native 在 iOS 平台上的使用惯例。

4.3 异常处理机制

iOS 平台实现了完整的异常捕获和处理机制:

kotlin 复制代码
try {
    // 核心逻辑
} catch(t: Throwable) {
    BridgeManager.callExceptionMethod(t.stackTraceToString())
}

通过 BridgeManager.callExceptionMethod 将 Kotlin 层的异常传递到原生层,便于统一的错误追踪和处理。

5. 生成代码示例

5.1 单模块场景生成代码

在单模块场景下,IOSTargetEntryBuilder 会生成类似以下的代码:

kotlin 复制代码
class KuiklyCoreEntry {
    var hrCoreDelegate: Delegate? = null
    private var hadRegisterNativeBridge: Boolean = false
    
    fun callKotlinMethod(methodId: Int, arg0: Any?, arg1: Any?, arg2: Any?, arg3: Any?, arg4: Any?, arg5: Any?) {
        try {
            if (!BridgeManager.isDidInit()) {
                BridgeManager.init()
                triggerRegisterPages()
            }
            
            if (!hadRegisterNativeBridge) {
                hadRegisterNativeBridge = true
                val nativeBridge = NativeBridge()
                nativeBridge.iosNativeBridgeDelegate = object : NativeBridge.IOSNativeBridgeDelegate {
                    override fun callNative(methodId: Int, arg0: Any?, arg1: Any?, arg2: Any?, arg3: Any?, arg4: Any?, arg5: Any?): Any? {
                        return hrCoreDelegate?.callNative(methodId, arg0, arg1, arg2, arg3, arg4, arg5)
                    }
                }
                BridgeManager.registerNativeBridge(arg0 as String, nativeBridge)
            }
            
            BridgeManager.callKotlinMethod(methodId, arg0, arg1, arg2, arg3, arg4, arg5)
        } catch(t: Throwable) {
            BridgeManager.callExceptionMethod(t.stackTraceToString())
        }
    }
    
    interface Delegate {
        fun callNative(methodId: Int, arg0: Any?, arg1: Any?, arg2: Any?, arg3: Any?, arg4: Any?, arg5: Any?): Any?
    }
    
    companion object {
        private var hadRegisterPages: Boolean = false
        
        fun isPageExist(pageName: String): Boolean {
            triggerRegisterPages()
            return BridgeManager.isPageExist(pageName)
        }
        
        private fun triggerRegisterPages() {
            if(!hadRegisterPages) {
                BridgeManager.registerPageRoute("PageA", PageA::class)
                BridgeManager.registerPageRoute("PageB", PageB::class)
                hadRegisterPages = true
            }
        }
    }
}

5.2 多模块场景生成代码

主模块生成代码
kotlin 复制代码
// 主模块代码 (isMainModule = true, subModules = "moduleA&moduleB")
class KuiklyCoreEntry {
    // ... 与单模块相同的属性和方法
    
    companion object {
        private var hadRegisterPages: Boolean = false
        
        fun isPageExist(pageName: String): Boolean {
            triggerRegisterPages()
            return BridgeManager.isPageExist(pageName)
        }
        
        private fun triggerRegisterPages() {
            if(!hadRegisterPages) {
                // 注册主模块页面
                BridgeManager.registerPageRoute("MainPage", MainPage::class)
                
                // 调用子模块注册
                KuiklyCoreEntry_moduleA.triggerRegisterPages()
                KuiklyCoreEntry_moduleB.triggerRegisterPages()
                
                hadRegisterPages = true
            }
        }
    }
}
子模块生成代码
kotlin 复制代码
// 子模块代码 (isMainModule = false, moduleId = "moduleA")
object KuiklyCoreEntry_moduleA {
    fun triggerRegisterPages() {
        // 注册子模块页面
        BridgeManager.registerPageRoute("ModuleAPage1", ModuleAPage1::class)
        BridgeManager.registerPageRoute("ModuleAPage2", ModuleAPage2::class)
    }
}

6. 泛化设计的优势

KuiklyUI 框架对 iOS 平台的泛化设计具有以下优势:

  1. 统一的抽象层 :通过继承自 KuiklyCoreAbsEntryBuilder,iOS 平台实现与其他平台保持一致的核心接口

  2. 平台特性适配:充分利用 iOS 开发中的委托模式和单例对象,符合 iOS 开发习惯

  3. 模块化支持 :通过 IOSMultiTargetEntryBuilder 支持灵活的模块化架构

  4. 完整的异常处理:全链路的异常捕获和上报机制,确保稳定性

  5. 高效的跨语言调用:基于 Kotlin/Native 技术实现高效的跨语言调用

相关推荐
whysqwhw5 小时前
kuiklyui core-ksp 鸿蒙
github
CoderJia程序员甲5 小时前
GitHub 热榜项目 - 日榜(2025-10-12)
ai·github·开源项目·github热榜
whysqwhw5 小时前
kuikly core-ksp 安卓
github
Tfly__6 小时前
Ubuntu 20.04 安装Aerial Gym Simulator - 基于 Gym 的无人机强化学习仿真器
linux·人工智能·ubuntu·github·无人机·强化学习·运动规划
CoderJia程序员甲8 小时前
GitHub 热榜项目 - 日榜(2025-10-13)
ai·开源·大模型·github·ai教程
uhakadotcom9 小时前
coze的AsyncTokenAuth和coze的TokenAuth有哪些使用的差异?
后端·面试·github
平平无奇。。。10 小时前
版本控制器之Git理论与实战
linux·git·gitee·github
kingg11 小时前
【征文计划】基于 Rokid JSAR 的 2D 粒子画廊实现:从技术概述到核心代码解析
github
绝无仅有11 小时前
面试真实经历某商银行大厂Java问题和答案总结(一)
后端·面试·github