Kam*_*hev 7 ios kotlin kotlin-native kotlin-multiplatform
我正在尝试实现一个观察者,以更改 UserDefaults 中给定键的值,该值来自用 Kotlin/Native 编写的多平台项目的 ios 本机部分。这是我写的代码:
fun subscribeForDataChange(storeName: String, callback: () -> Unit) {
NSUserDefaults(storeName).addObserver(
object : NSObject() {
fun observeValue(
observer: NSObject,
forKeyPath: String,
options: NSKeyValueObservingOptions,
context: COpaquePointer?
) {
callback()
print("Data Changed!!!")
}
},
options = NSKeyValueObservingOptionNew,
forKeyPath = DATA_KEY,
context = null
)
}
Run Code Online (Sandbox Code Playgroud)
问题是我从来没有收到通知,很可能是因为observeValueNSObject 中没有定义,但是我还应该做什么才能实现这一点?
这是同一组中的 2 个应用程序共享 UserDefaults 的解决方案。我在两个进程之间共享 SQLite 数据库,并且我需要知道一个进程何时将 somethink 写入数据库。经典流不会被触发,因此我编写了一个流助手,当 NSUserDefaults 更改时,它会在 Kotlin 中发出值。
NSObject作为 Swift 代码库的一部分实现( Swift 代码灵感)。当 NSUserDefaults 更改时,Swift 会调用 Kotlin 方法。首先定义接口。
interface NSUserDefaultsKotlinHelper {
fun userDefaultsChanged()
}
interface SwiftInjector {
fun injectIntoSwift(nsUserDefaultsKotlinHelper: NSUserDefaultsKotlinHelper?)
}
Run Code Online (Sandbox Code Playgroud)
让该接口将侦听器注入到 Swift 代码中:
class InterprocessObserver: NSObject, SwiftInjector {
let key: String = "interprocess_communication"
private var nsUserDefaultsKotlinHelper : NSUserDefaultsKotlinHelper?
private let userDefaults = UserDefaults.init(suiteName: "group.your.group.id")
override init() {
super.init()
userDefaults?.addObserver(self, forKeyPath: key, options: [.old, .new], context: nil)
}
func injectIntoSwift(nsUserDefaultsKotlinHelper: NSUserDefaultsKotlinHelper?) {
self.nsUserDefaultsKotlinHelper = nsUserDefaultsKotlinHelper
}
func dataChangedFromAnotherProcess(data : [AnyHashable : Any]) {
userDefaults?.set(data, forKey: key)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
guard let _ = change, object != nil, keyPath == key else { return }
nsUserDefaultsKotlinHelper?.userDefaultsChanged()
}
deinit {
userDefaults?.removeObserver(self, forKeyPath: key, context: nil)
}
}
Run Code Online (Sandbox Code Playgroud)
在 Kotlin 中注入侦听器 - 我将在流开始收集时注入:
class InterProcessCommunication(val interPlatformInjector: InterplatformInjector) : InterplatformInjector by interplatformInjector {
val testFlow: Flow<Emitter> = flow {
val channel = Channel<Emitter>(CONFLATED)
channel.trySend(Emitter.STAY_CALM)
val listener = object : IInterprocessCommunication {
override fun interProcessChanged() {
channel.trySend(Emitter.EMIT)
}
}
interPlatformInjector.injectListener(listener)
try {
for (item in channel) {
emit(item)
}
} finally {
interPlatformInjector.injectListener(null)
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用 Koin 创建对象将是:
//Swift
func initObservers() {
let interplatformInjector = InterprocessObserver()
initKoin(interplatformInjector : interplatformInjector)
}
//Kotlin
fun initKoin(interplatformInjector : InterplatformInjector){
startKoin {
module {
single {InterProcessCommunication(interplatformInjector)}
}
}
}
//Swift Second process (for example NotificationService)
func dataChanged(interprocessObserver : InterprocessObserver) {
interprocessObserver.dataChangedFromAnotherProcess(data) //data could be anythink - for example a string
}
Run Code Online (Sandbox Code Playgroud)
该方法dataChenged()将触发 Kotlin 流程。这是你想要的?
| 归档时间: |
|
| 查看次数: |
799 次 |
| 最近记录: |