You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将KMM库日志共享至iOS(Swift)及Android应用

实现KMM日志向Swift应用的传递

针对你需要将KMM库的日志共享到Swift端的需求,这里提供几种对应Swift代理/通知模式的KMM实现方案,结合你正在使用的Napier日志框架来落地:

方案1:Kotlin接口(对应Swift协议)回调代理

这个方案完全对应Swift的代理模式,逻辑直观,适合单条日志的实时传递:

  1. 在KMM的Common模块定义日志回调接口和级别枚举
interface LogCallback {
    fun onLog(message: String, level: LogLevel)
}

enum class LogLevel {
    VERBOSE, DEBUG, INFO, WARNING, ERROR
}
  1. 自定义Napier日志引擎,将日志转发到回调接口
class CallbackLogger(private val callback: LogCallback) : Napier.LogEngine {
    override fun performLog(priority: Napier.LogLevel, tag: String?, throwable: Throwable?, message: String?) {
        val logContent = buildString {
            append(tag?.let { "[$it] " } ?: "")
            append(message ?: "")
            throwable?.let { append("\n${it.stackTraceToString()}") }
        }
        callback.onLog(logContent, mapNapierLevel(priority))
    }

    private fun mapNapierLevel(napierLevel: Napier.LogLevel): LogLevel {
        return when(napierLevel) {
            Napier.LogLevel.VERBOSE -> LogLevel.VERBOSE
            Napier.LogLevel.DEBUG -> LogLevel.DEBUG
            Napier.LogLevel.INFO -> LogLevel.INFO
            Napier.LogLevel.WARNING -> LogLevel.WARNING
            Napier.LogLevel.ERROR -> LogLevel.ERROR
        }
    }
}
  1. 在KMM核心业务类中提供回调设置入口
class PosTerminalManager {
    var logCallback: LogCallback? = null

    init {
        Napier.base(CallbackLogger(object : LogCallback {
            override fun onLog(message: String, level: LogLevel) {
                logCallback?.onLog(message, level)
            }
        }))
    }
}
  1. Swift端实现对应协议并绑定
class AppLogHandler: LogCallback {
    func onLog(message: String, level: LogLevel) {
        // 这里可以执行日志收集逻辑:写入本地文件、上报服务器等
        print("KMM 日志 [\(level.rawValue)]: \(message)")
    }
}

// 使用时绑定
let terminalManager = PosTerminalManager()
terminalManager.logCallback = AppLogHandler()

方案2:Kotlin Flow响应式日志流

这个方案对应Swift的Combine/AsyncSequence,适合批量日志处理或实时订阅场景:

  1. 在Common模块定义日志流和数据结构
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow

class LogFlowManager {
    private val _logFlow = MutableSharedFlow<LogEntry>()
    val logFlow = _logFlow.asSharedFlow()

    data class LogEntry(val message: String, val level: LogLevel)

    enum class LogLevel {
        VERBOSE, DEBUG, INFO, WARNING, ERROR
    }
}
  1. 实现Flow版Napier日志引擎
class FlowLogger(private val logFlowManager: LogFlowManager) : Napier.LogEngine {
    override fun performLog(priority: Napier.LogLevel, tag: String?, throwable: Throwable?, message: String?) {
        val logContent = buildString {
            append(tag?.let { "[$it] " } ?: "")
            append(message ?: "")
            throwable?.let { append("\n${it.stackTraceToString()}") }
        }
        val logLevel = when(priority) {
            Napier.LogLevel.VERBOSE -> LogFlowManager.LogLevel.VERBOSE
            Napier.LogLevel.DEBUG -> LogFlowManager.LogLevel.DEBUG
            Napier.LogLevel.INFO -> LogFlowManager.LogLevel.INFO
            Napier.LogLevel.WARNING -> LogFlowManager.LogLevel.WARNING
            Napier.LogLevel.ERROR -> LogFlowManager.LogLevel.ERROR
        }
        kotlinx.coroutines.GlobalScope.launch {
            logFlowManager._logFlow.emit(LogFlowManager.LogEntry(logContent, logLevel))
        }
    }
}
  1. 在KMM核心类中初始化
class PosTerminalManager {
    val logFlowManager = LogFlowManager()

    init {
        Napier.base(FlowLogger(logFlowManager))
    }
}
  1. Swift端订阅日志流
let terminalManager = PosTerminalManager()
// 用Async/Await订阅处理
Task {
    for await logEntry in terminalManager.logFlowManager.logFlow {
        print("KMM 流式日志 [\(logEntry.level.rawValue)]: \(logEntry.message)")
        // 执行自定义日志收集逻辑
    }
}

注意事项

  • 替换Napier默认引擎时,确保在KMM库初始化阶段完成,避免日志遗漏
  • Swift端处理回调或订阅时,注意用弱引用避免内存泄漏
  • 日志级别枚举在KMM和Swift端会自动映射,保持定义一致即可

内容的提问来源于stack exchange,提问作者lucgian841

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 16:40:17