ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Follow publication

Leveraging Key-Value Observing (KVO) in Kotlin Multiplatform (KMP) for iOS

André Mion
ProAndroidDev
Published in
3 min readMar 4, 2024

What is Key-Value Observing (KVO)?

internal class AudioPlayerImpl: NSObject, AudioPlayer {

private let player = AVPlayer()
private var observation: NSKeyValueObservation?

override init() {
super.init()

addObserver(self, forKeyPath: "timeControlStatus", options: [.new], context: nil)
}

override func observeValue(
forKeyPath keyPath: String?,
of: Any?,
change: [NSKeyValueChangeKey: Any]?,
context: UnsafeMutableRawPointer?
) {
print("\(keyPath!) has been updated to: \(change![.newKey]!)")
}
}

KVO in KMP iOS

Mixing Kotlin and Objective-C supertypes is not supported
'observeValueForKeyPath' overrides nothing
What should we do?

🛟 Cinterops for the rescue!

package = platform.foundation
language = Objective-C
---
#import <Foundation/Foundation.h>

@protocol NSKeyValueObserving
@required
- (void) observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary<NSKeyValueChangeKey, id> *)change
context:(void *)context;
@end;
kotlin {
androidTarget()

listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach { target ->
target.binaries.framework {
baseName = "shared"
isStatic = true
}
target.compilations.getByName("main") {
// The default file path is src/nativeInterop/cinterop/<interop-name>.def
val nskeyvalueobserving by cinterops.creating
}
}
}
internal class AudioPlayerImpl: AudioPlayer {

private val player = AVPlayer()

init {
player.addObserver(
observer = timeControlObserver,
forKeyPath = "timeControlStatus",
options = NSKeyValueObservingOptionNew,
context = null
)
}

private val timeControlObserver: NSObject = object : NSObject(), NSKeyValueObservingProtocol {

override fun observeValueForKeyPath(
keyPath: String?,
ofObject: Any?,
change: Map<Any?, *>?,
context: COpaquePointer?
)
{
println("${keyPath} has been updated to: ${change!![NSKeyValueChangeNewKey]!!}")
}
}
}
}
player.removeObserver(timeControlObserver, "timeControlStatus")

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Published in ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Written by André Mion

🇧🇷 Android Engineer living in 🇵🇹 • Full time Husband and Dad • Occasionally Drummer and Inline Skater… I write mostly about Android and Tech…

Responses (1)

Write a response