возможно ли использовать ожидание / фактическое объявление класса с помощью этого метода? Если да, то как?

ел бы включить файл Kotlin, который выполняет только обработку данных и сетевые операции в существующем проекте iOS, сохраняя при этом собственный код пользовательского интерфейса iOS.

Хотя я думал, что это может быть достигнуто сКотлин / РоднойОбразцы iOS (1,2), что я обнаружил, что использование Kotlin / Native, кажется, берет на себя и код пользовательского интерфейса iOS.

Возможно ли включение файла Kotlin для передачи данных в iOS с помощью Kotlin / Native, не касаясь кода пользовательского интерфейса, и если да, то каковы шаги для этого?

 tskulbru01 дек. 2017 г., 23:11
Вы также должны взглянуть наgithub.com/JetBrains/kotlinconf-app для большего количества примеров iOS
 CryptUser02 дек. 2017 г., 01:41
Спасибо за упоминание этого примера. Это еще одна отличная демонстрация того, что может сделать Kotlin / Native. Однако, как и в приведенных мною примерах, он по существу реализует все, включая пользовательский интерфейс в Kotlin, в то время как нативный подкласс (ы) iOS UIViewController и AppDelegate по существу пусты У меня есть тысячи строк собственного кода пользовательского интерфейса iOS (много подклассов UIViewController), которые я хотел бы сохранить, и интересно, возможно ли это с помощью Kotlin / Native?

Ответы на вопрос(2)

если хотите, поэтому код kotlin остается в файле фреймворка, так что вы можете использовать некоторый общий код как на Android, так и на iOS без написания полного приложения для iOS на kotlin.

Используйте gradle для сборки кода kotlin в совместимой с objc / swift инфраструктуре

В вашем файле build.gradle

buildscript {
    ext.kotlin_native_version = '0.5'
    repositories {
        mavenCentral()
        maven {
            url "https://dl.bintray.com/jetbrains/kotlin-native-dependencies"
        }
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-native-gradle-plugin:$kotlin_native_version"
    }
}
group 'nz.salect'
version '0.1'
apply plugin: "konan"
konan.targets = ["iphone", "iphone_sim"]
konanArtifacts {
    framework('nativeLibs')
}

Он сгенерирует два файла .framework, один для симулятора, другой для реального устройства, поместит фреймворк в ваш проект и свяжет его с вашим проектом как любой другой фреймворк стороннего производителя.

Cmd: ./gradlew build

Примечание. Каждый раз, когда вы изменяете свои файлы kotlin, также создаете и заменяете свой файл фреймворка (вы можете создать сценарий оболочки и добавить его для этапов сборки, чтобы сделать это автоматически).

Ура !!!

 Nishita09 авг. 2018 г., 07:37
возможно ли использовать ожидание / фактическое объявление класса с помощью этого метода? Если да, то как?

в кроссплатформенном проекте можно передавать данные между Kotlin и собственным кодом пользовательского интерфейса iOS с помощью Kotlin / Native. Это позволяет иметь общую кодовую базу для модели данных, основанной на Kotlin, в то время как, например, продолжая использовать собственный код пользовательского интерфейса для iOS.

Оригинальное доказательство:

Проектhttps://github.com/justMaku/Kotlin-Native-with-Swift указал мне правильное направление, так как оно показывает основные шаги для этого:

В Swift UIViewController он вызывает функцию-обертку, которая должна получить строку из функции Kotlin. Вызов осуществляется через слой C ++, который сам запускает среду выполнения Kotlin, передает запрос в функцию Kotlin, получает от нее строку и передает ее обратно Swift UIViewController, который затем отображает ее.

На техническом уровне проект содержит скрипт, который компилирует части Kotlin, C ++ и Kotlin / Native в статическую библиотеку, которую затем можно вызывать из собственного проекта iOS.

Чтобы заставить код работать, мне пришлось (после клонирования из git) выполнить «синхронизацию подмодуля git» перед запуском «./setup.sh».

Для передачи данных с помощью модели данных, основанной на Kotlin, я хотел бы иметь универсальную функцию, которая может передавать данные в Kotlin, изменять эти данные и возвращать результат обратно в собственный код iOS. В качестве доказательства принципа, что такая функция может быть построена, я расширил проект, чтобы не только получить строку из Kotlin, но и отправить ее в Kotlin, добавить ее и отправить результат обратно.

Продление проекта:

Поскольку в этом, казалось бы, простом расширении были некоторые препятствия, я изложил шаги для всех, кто заинтересован. Если вы будете следовать, вы должны увидеть следующее:

Текст может быть глупым, но он говорит вам, что происходит. Изменения в ViewController.swift в функции viewDidAppear:

    let swiftMessage: String = "Hello Kotlin, this is Swift!"
    let cStr = swiftMessage.cString(using: String.Encoding.utf8)
    if let retVal = kotlin_wrapper(cStr) {
        let string = String(cString: retVal)
        ...
    }

Вы видите текст, который Swift отправляет в Kotlin в функции-обертке (в конце концов, будет отображена результирующая переменная 'string'). Можно напрямую передать строку Swift в оболочку, но я хотел подчеркнуть, что оболочка будет рассматривать ввод и вывод как c-строки. Действительно, файл Kotlin Native-Bridging-Header.h внутри собственного проекта iOS теперь становится:

extern const char* kotlin_wrapper(const char* swiftMessage);

На нем идет файл Launcher.cpp. Посколькуисходный файл использовал KString в качестве значения результата kotlin_main, я пытался некоторое времяконвертировать const char * в KString и передать это kotlin_main. В конце концов я обнаружил, что гораздо проще напрямую передать переменные const char * в Kotlin и выполнить там преобразование с помощью функций, которые нам дал Kotlin / Native.

Мой Launcher.cpp стал компактнее оригинала. Вот полный файл:

#include "Memory.h"
#include "Natives.h"
#include "Runtime.h"
#include "KString.h"
#include <stdlib.h>
#include <string>

extern "C" const char* kotlin_main(const char* swiftMessageChar);

extern "C" const char* kotlin_wrapper(const char* swiftMessageChar) {
    RuntimeState* state = InitRuntime();
    if (state == nullptr) {
        return "Failed to initialize the kotlin runtime";
    }
    const char* exitMessage = kotlin_main(swiftMessageChar);
    DeinitRuntime(state);
    return exitMessage;
}

Вы видите, как оболочка сначала запускает среду выполнения Kotlin, а затем вызывает функцию kotlin_main, которая находится в файле kotlin.kt:

import konan.internal.ExportForCppRuntime
import kotlinx.cinterop.CPointer
import kotlinx.cinterop.ByteVar
import kotlinx.cinterop.cstr
import kotlinx.cinterop.nativeHeap
import kotlinx.cinterop.toKString

@ExportForCppRuntime

fun kotlin_main(cPtr: CPointer<ByteVar>): CPointer<ByteVar> {
    val swiftMessage = cPtr.toKString()
    val kotlinMessage = "Hello Swift, I got your message: '$swiftMessage'."
    val returnPtr = kotlinMessage.cstr.getPointer(nativeHeap)
    return returnPtr
}

Указатель преобразуется в строку Kotlin, а затем используется при создании сообщения kotlinMessage (пример преобразования данных). Сообщение о результате затем преобразуется обратно в указатель и передается через оболочку обратно в Swift UIViewController.

Куда пойти отсюда?

В принципе, можно использовать эту структуру, не затрагивая слой C ++ снова. Просто определите функции pack и unpack, которые упаковывают произвольные типы данных в строку и распаковывают строку в соответствующий тип данных на другой стороне. Такие функции упаковки и распаковки должны быть написаны только один раз для каждого языка и могут использоваться повторно для различных проектов, если они выполняются достаточно обобщенно. На практике я, вероятно, сначала переписал бы приведенный выше код для передачи двоичных данных, а затем написал функции pack и unpack для преобразования произвольных типов данных в двоичные данные и из них.

 Nishita09 авг. 2018 г., 07:29
Могу ли я использовать ожидаемое и фактическое объявление класса с помощью kotlin / native для ios?

Ваш ответ на вопрос