#ios #kotlin
#iOS #kotlin
Вопрос:
Я пытался получить веб-страницу на Kotlin / Native с платформой iOS, но это не сработало. Пожалуйста, скажите мне, в чем проблема.
Я создал проект с помощью Gradle и build.gradle
содержит:
plugins {
id 'kotlin-multiplatform' version '1.3.21'
}
Вот коды.
package sample
fun main(args: Array<String>) {
println(WebGateway.get("https://www.google.com/"))
}
package sample
import platform.Foundation.*
import platform.darwin.*
actual object WebGateway {
actual fun get(urlString: String): String {
val semaphore = dispatch_semaphore_create(0)
var components = NSURLComponents(urlString)
val url = components.URL
var result: String = ""
val config = NSURLSessionConfiguration.defaultSessionConfiguration()
config.waitsForConnectivity = true
config.timeoutIntervalForResource = 300.0
val session = NSURLSession.sessionWithConfiguration(
config, null, NSOperationQueue.mainQueue()
)
val task = session
.dataTaskWithURL(url!!) { nsData: NSData?, nsurlResponse: NSURLResponse?, nsError: NSError? ->
nsData?.run { result = toString() }
println(nsData)
dispatch_semaphore_signal(semaphore);
}
task.resume()
session.finishTasksAndInvalidate()
NSOperationQueue.mainQueue().waitUntilAllOperationsAreFinished()
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
return result
}
}
После сборки приложения main.kexe
было создано.
Я ожидал, что HTML веб-страницы Google будет напечатан в стандартном выводе при выполнении приложения. Но на самом деле:
% ./main.kexe
Он ничего не показывает.
Программа останавливается на dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
.
После выполнения приложения task.state
стало NSURLSessionTaskStateCompleted
, но программа ничего не показывает и не завершается.
Когда я изменил session
на NSURLSession.sessionWithConfiguration(config)
, я получил следующий результат.
% ./main.kexe
Uncaught Kotlin exception: kotlin.native.IncorrectDereferenceException: illegal attempt to access non-shared sample.WebGateway.$<anonymous>$FUNCTION_REFERENCE$0@f6f058e8 from other thread
at 0 main.kexe 0x000000010039c3c3 ThrowIllegalObjectSharingException 595
at 1 main.kexe 0x00000001003b9d6d -[KotlinObjectHolder ref] 141
at 2 main.kexe 0x00000001003c9524 platform_Foundation_kniBridge11046 148
at 3 main.kexe 0x00000001003ca18c __platform_Foundation_kniBridge11045_block_invoke 108
at 4 CFNetwork 0x00007fff4cd80763 __75-[__NSURLSessionLocal taskForClass:request:uploadFile:bodyData:completion:]_block_invoke 19
at 5 CFNetwork 0x00007fff4cd8016c __49-[__NSCFLocalSessionTask _task_onqueue_didFinish]_block_invoke 172
at 6 Foundation 0x00007fff50243a47 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ 7
at 7 Foundation 0x00007fff5024394e -[NSBlockOperation main] 68
at 8 Foundation 0x00007fff50218f7a -[__NSOperationInternal _start:] 686
at 9 Foundation 0x00007fff5024367f __NSOQSchedule_f 227
at 10 libdispatch.dylib 0x00007fff7aef3d4f _dispatch_call_block_and_release 12
at 11 libdispatch.dylib 0x00007fff7aef4dcb _dispatch_client_callout 8
at 12 libdispatch.dylib 0x00007fff7aef75d8 _dispatch_continuation_pop 427
at 13 libdispatch.dylib 0x00007fff7aef6c7a _dispatch_async_redirect_invoke 718
at 14 libdispatch.dylib 0x00007fff7af02d1a _dispatch_root_queue_drain 325
at 15 libdispatch.dylib 0x00007fff7af034b1 _dispatch_worker_thread2 90
at 16 libsystem_pthread.dylib 0x00007fff7b1346ee _pthread_wqthread 619
at 17 libsystem_pthread.dylib 0x00007fff7b134415 start_wqthread 13
zsh: abort ./main.kexe
Когда я изменил session
на NSURLSession.sharedSession()
, появилась та же ошибка.
Комментарии:
1. Есть какие-либо успехи в этом?
2. Есть новости по этому поводу?
Ответ №1:
Kotlin native ожидает, что обратный вызов будет вызван в основном потоке. Вот как собственный HTTP-запрос реализован в приложении Kotlin conf spinner.
Комментарии:
1. Также можно вызвать put запрос внутри NSOperationQueue.mainQueue.addOperationWithBlock { }