我一直试图使用共享模块KMM将图像上传到aws s3服务器。它在Android中运行得很好,但是在iOS中我得到了这个问题:- Uncaught Kotlin exception: kotlin.native.IncorrectDereferenceException: illegal attempt to access non-shared
现在,尽管我已经对此进行了大量的搜索,我已经知道它与frozen()有关,但我不知道它是什么,以及如何解决这个问题。
代码:-
actual class ClassName {
init {
ensureNeverFrozen()
}
actual fun imageUpload() {
var credentialsProvider = AWSCognitoCredentialsProvider(regionType = // Region here, identityPoolId = //identityPoolId here)
var configuration = AWSServiceConfiguration(region = // Region here, credentialsProvider = //credentialsProvider here)
AWSServiceManager.defaultServiceManager()?.defaultServiceConfiguration = configuration
val expression = AWSS3TransferUtilityUploadExpression()
// Start uploading using AWSS3TransferUtility
val awsTransferUtility = AWSS3TransferUtility.defaultS3TransferUtility()
val completionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock
completionHandler = { _: AWSS3TransferUtilityUploadTask?, error: NSError? ->
if (error == nil) {
val url = AWSS3.defaultS3().configuration.endpoint()?.URL()
val publicURL = url?.URLByAppendingPathComponent("bucketName")?.URLByAppendingPathComponent("fileName")
// Image Upload Complete
} else {
// Image Upload failure
}
}
awsTransferUtility.uploadFile(
fileUrl!!,
bucket = "bucketName",
key = "fileName",
contentType = ".image",
expression = expression,
completionHandler = completionHandler. // Error pointed on this line
)
}
}现在,当我调用该函数时,我的应用程序就会崩溃,指向completionHandler。
错误日志:-
Uncaught Kotlin exception: kotlin.native.IncorrectDereferenceException: illegal attempt to access non-shared ClassName.$imageUpload$lambda-1$lambda-0$FUNCTION_REFERENCE$1@2803dc8 from other thread
at 0 iosApp 0x000000010cc1984f kfun:kotlin.Throwable#<init>(kotlin.String?){} + 95
at 1 iosApp 0x000000010cc138cd kfun:kotlin.Exception#<init>(kotlin.String?){} + 93
at 2 iosApp 0x000000010cc139fd kfun:kotlin.RuntimeException#<init>(kotlin.String?){} + 93
at 3 iosApp 0x000000010cc327fd kfun:kotlin.native.IncorrectDereferenceException#<init>(kotlin.String){} + 93
at 4 iosApp 0x000000010cc3461f ThrowIllegalObjectSharingException + 623
at 5 iosApp 0x000000010cd16fc2 _ZN12_GLOBAL__N_128throwIllegalSharingExceptionEP9ObjHeader + 34
at 6 iosApp 0x000000010cd170fd _ZN12_GLOBAL__N_136terminateWithIllegalSharingExceptionEP9ObjHeader + 13
at 7 iosApp 0x000000010cd1af0a _ZNK16KRefSharedHolder3refIL11ErrorPolicy3EEEP9ObjHeaderv + 58
at 8 iosApp 0x000000010cbf53ca _ZL39Kotlin_Interop_unwrapKotlinObjectHolderP11objc_object + 42
at 9 iosApp 0x000000010cbee050 _4b4d4d4c69623a736861726564_knbridge15 + 224
at 10 AWSS3 0x000000010d84509e -[AWSS3TransferUtility URLSession:task:didCompleteWithError:] + 4814发布于 2021-08-03 03:20:10
用于预览的本地并发模型可用。看看新内存模型迁移指南。发布后,您不应该面临任何这样的问题,但在此之前,上述答案是有效的。
尝试调用completionHandler.freeze()
或者,将处理程序移动到函数调用(而不将其存储在变量中)。
如果在处理程序中使用外部作用域的一些变量,它们可能也需要冻结。如果前两种方法都不起作用,那么试着用print()替换完成部分的内容,看看是否有用,如果有用--逐个取消代码部分的注释来本地化有问题的行。
KMM并发模型禁止从不同线程访问可变对象,freeze使对象不可变,因此可以从不同线程使用。
有了coroutines对象,就会在需要时自动冻结,但是当您切换没有协同的线程时,您必须手动完成。
这正是这里所发生的事情: AWS从另一个线程调用completionHandler (对于完成的方法来说这是很常见的)
在这里查看更多关于并发模型的信息:https://kotlinlang.org/docs/mobile/concurrency-overview.html
这种行为是我们现在必须用KMM来处理的,但很快它就会改变,这是从alpha到release的主要阻止器KMM,JetBrains团队专注于解决这个特定的问题,因此我们不必再使用freeze()了。
发布于 2022-04-16 11:03:05
将下面添加到gradle.properties中
kotlin.native.binary.memoryModel=experimental
kotlin.native.binary.freezing=disabledhttps://stackoverflow.com/questions/68625732
复制相似问题