Я пытаюсь использовать Kotlin MPP (Multiplatform) для разработки общей библиотеки между Android и iOS. Но я сталкиваюсь с проблемой потоков iOS. Для моего приложения в iOS я устанавливаю sh объект в основном потоке, но он, вероятно, вызывает функцию в другом потоке и выдает это исключение следующим образом:
Uncaught Kotlin exception: kotlin.native.IncorrectDereferenceException: illegal attempt to access non-shared example.api.DrivingBehaviorDetector@397cba8 from other thread
at 0 DrivingBehaviorDetector 0x00000001037619d7 kfun:kotlin.Throwable.<init>(kotlin.String?)kotlin.Throwable + 87
at 1 DrivingBehaviorDetector 0x000000010375bca5 kfun:kotlin.Exception.<init>(kotlin.String?)kotlin.Exception + 85
at 2 DrivingBehaviorDetector 0x000000010375b9a5 kfun:kotlin.RuntimeException.<init>(kotlin.String?)kotlin.RuntimeException + 85
at 3 DrivingBehaviorDetector 0x0000000103781395 kfun:kotlin.native.IncorrectDereferenceException.<init>(kotlin.String)kotlin.native.IncorrectDereferenceException + 85
at 4 DrivingBehaviorDetector 0x0000000103782568 ThrowIllegalObjectSharingException + 744
at 5 DrivingBehaviorDetector 0x00000001037d72bc _ZNK27BackRefFromAssociatedObject19ensureRefAccessibleEv + 76
at 6 DrivingBehaviorDetector 0x00000001037c97c3 -[KotlinBase toKotlin:] + 35
at 7 DrivingBehaviorDetector 0x00000001037e3ef1 Kotlin_ObjCExport_refFromObjC + 65
at 8 DrivingBehaviorDetector 0x00000001037c4e37 objc2kotlin.125 + 167
at 9 Test 0x000000010340224d $sIeg_IeyB_TR + 45 (/Users/james/Documents/Projects/go/TestMPPforiOS/<compiler-generated>:<unknown>)
at 10 libdispatch.dylib 0x0000000103959dd4 _dispatch_call_block_and_release + 12
at 11 libdispatch.dylib 0x000000010395ad48 _dispatch_client_callout + 8
at 12 libdispatch.dylib 0x000000010396c460 _dispatch_root_queue_drain + 819
at 13 libdispatch.dylib 0x000000010396cb96 _dispatch_worker_thread2 + 132
at 14 libsystem_pthread.dylib 0x00007fff5245f6b3 _pthread_wqthread + 583
at 15 libsystem_pthread.dylib 0x00007fff5245f3fd start_wqthread + 13
(lldb)
Я рассматриваю решение в этих статьи:
Неизменяемость в Kotlin / Native: Неизменяемость в Kotlin / Native
Сопрограммы и неизменность K / N: Сопрограммы и неизменность K / N .
Вход в мой API (разделяемая библиотека) выглядит следующим образом:
class DrivingBehaviorDetector (
private var gravity:Vector?,
private var front:Vector?,
onGravityOrFrontChanged: ((newGravity: Vector?, newFront: Vector?, timestamp: Long) -> Unit)?,
onDrivingEventDetected: ((event: DrivingEvent) -> Unit)?
) {
private val lowPassFilter = LowPassFilter()
private val accProcessor = AccProcessor(gravity, front, onGravityOrFrontChanged, onDrivingEventDetected)
init {
gravity = gravity?.toCoreUnit()
front = front?.toCoreUnit()
}
fun addData(data:Acceleration) {
val rawAcc = data.toCoreUnit()
val filterAcc = lowPassFilter.lowPass(rawAcc)
accProcessor.addData(filterAcc)
}
fun addData(data:List<Acceleration>) {
for(acc in data) {
addData(acc)
}
}
}
Мы можем заметить, что API настолько прост, что предоставляет большое количество данных и вызывает результаты некоторых расчеты. Но в iOS выведите исключение и код, как показано ниже:
let drivingBehaviorDetector = DrivingBehaviorDetector(gravity: nil, front: nil, onGravityOrFrontChanged: { (newGravity, newFront, timestamp) in
print("newGravity = \(newGravity)")
print("newFront = \(newFront)")
}) { (event) in
print("event = \(event.description())")
}
let acc1 = Acceleration(vector: Vector(x: 0, y: 0, z: 0))
let acc2 = Acceleration(vector: Vector(x: 0, y: 100, z: 0))
drivingBehaviorDetector.addData(data: acc1)
DispatchQueue.global(qos: .background).async {
drivingBehaviorDetector.addData(data: acc2)
}
Единственное решение, которое я могу себе представить, - это принудительно использовать API в том же потоке, но это кажется немного странным. Можно ли решить эту проблему путем изменения общей библиотеки. Потому что мю использовать просто как «DrivingBehaviorDetector», но это может быть вызов функции «addData» в другом потоке. Спасибо за ответы.