Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Выходные с Kotlin/Native

CocoaHeads
September 29, 2018

Выходные с Kotlin/Native

CocoaHeads

September 29, 2018
Tweet

More Decks by CocoaHeads

Other Decks in Programming

Transcript

  1. • Избавиться от дублирования кода • Увеличить качество тестирования •

    Гарантия одинакового поведения 3 Зачем это нужно?
  2. • Избавиться от дублирования кода • Увеличить качество тестирования •

    Гарантия одинакового поведения 4 Зачем это нужно?
  3. • Избавиться от дублирования кода • Увеличить качество тестирования •

    Гарантия одинакового поведения 5 Зачем это нужно?
  4. 7 Сначала немного про архитектуру Вью Контроллеры Приложение Юзкейсы и

    юзерфлоу Платформа База данных Транспорт Многопоточность Логин пользователя Просмотр профиля Создание поста Объединяет Изображения Текстовые поля Списки Экран логина Экран профиля Экран ленты Навигация
  5. 8 C++ Вью Контроллеры Приложение Юзкейсы и юзерфлоу Платформа База

    данных Транспорт Многопоточность Логин пользователя Просмотр профиля Создание поста Объединяет Изображения Текстовые поля Списки Экран логина Экран профиля Экран ленты Навигация
  6. 9 C++ и OpenGL(Deprecated) Вью Контроллеры Приложение Юзкейсы и юзерфлоу

    Платформа База данных Транспорт Многопоточность Логин пользователя Просмотр профиля Создание поста Объединяет Изображения Текстовые поля Списки Экран логина Экран профиля Экран ленты Навигация
  7. 10 QT Вью Контроллеры Приложение Юзкейсы и юзерфлоу Платформа База

    данных Транспорт Многопоточность Логин пользователя Просмотр профиля Создание поста Объединяет Изображения Текстовые поля Списки Экран логина Экран профиля Экран ленты Навигация
  8. 11 React Native Вью Контроллеры Приложение Юзкейсы и юзерфлоу Платформа

    База данных Транспорт Многопоточность Логин пользователя Просмотр профиля Создание поста Объединяет Изображения Текстовые поля Списки Экран логина Экран профиля Экран ленты Навигация
  9. 12 RN на самом деле Вью Контроллеры Приложение Юзкейсы и

    юзерфлоу Платформа База данных Транспорт Многопоточность Логин пользователя Просмотр профиля Создание поста Объединяет Изображения Текстовые поля Списки Экран логина Экран профиля Экран ленты Навигация
  10. 14 Kotlin/Native Вью Контроллеры Приложение Юзкейсы и юзерфлоу Платформа База

    данных Транспорт Многопоточность Логин пользователя Просмотр профиля Создание поста Объединяет Изображения Текстовые поля Списки Экран логина Экран профиля Экран ленты Навигация
  11. • Полное приложение на Kotlin/Native • Storyboards + Kotlin/Native •

    Kotlin/Native as Library 15 Как же этим воспользоваться?
  12. • Полное приложение на Kotlin/Native • Storyboards + Kotlin/Native •

    Kotlin/Native as Library 16 Как же этим воспользоваться?
  13. • Полное приложение на Kotlin/Native • Storyboards + Kotlin/Native •

    Kotlin/Native as Library 17 Как же этим воспользоваться?
  14. • Полное приложение на Kotlin/Native • Storyboards + Kotlin/Native •

    Kotlin/Native as Library 18 Как же этим воспользоваться?
  15. 19 Kotlin Build • Application -> .kexe • KN Library

    -> .klib • Native Library -> .framework • И многое другое
  16. 21 Kotlin/Native – Application import kotlinx.cinterop.* import platform.Foundation.* import platform.UIKit.*

    fun main(args: Array<String>) { memScoped { val argc = args.size + 1 val argv = (arrayOf("konan") + args).map { it.cstr.getPointer(memScope) }.toCValues() autoreleasepool { UIApplicationMain(argc, argv, null, NSStringFromClass(AppDelegate)) } } }
  17. 22 Kotlin/Native – Application import platform.Foundation.* import platform.UIKit.* class AppDelegate

    : UIResponder(), UIApplicationDelegateProtocol { companion object : UIResponderMeta(), UIApplicationDelegateProtocolMeta {} override fun init() = initBy(AppDelegate()) override fun application(application: UIApplication, didFinishLaunchingWithOptions: NSDictionary?): Boolean { var window = UIWindow() window.rootViewController = ViewController() window.makeKeyAndVisible() this.setWindow(window) return true } private var _window: UIWindow? = null override fun window() = _window override fun setWindow(window: UIWindow?) { _window = window } }
  18. 23 Kotlin/Native – Application import platform.Foundation.* import platform.UIKit.* import platform.CoreGraphics.*

    class ViewController : UIViewController { constructor(): super(null, null) override fun viewDidLoad() { super.viewDidLoad() this.view.backgroundColor = UIColor.whiteColor() val label = UILabel() label.frame = CGRectMake(5.0, 50.0, 150.0, 30.0) label.text = "Hello from Kotlin" this.view.addSubview(label) } }
  19. 29 Kotlin/Native + Storyboards import platform.Foundation.* import platform.UIKit.* @ExportObjCClass class

    ViewController: UIViewController { @OverrideInit constructor(coder: NSCoder) : super(coder) @ObjCOutlet lateinit var label: UILabel @ObjCOutlet lateinit var textField: UITextField @ObjCOutlet lateinit var btn: UIButton @ObjCAction fun btnPressed() { label.text = "Kotlin says: 'Hello, ${textField.text}!'" } }
  20. 31 Kotlin/Native as Framework • Domain Knowledge • Тестирование •

    Модульность архитектуры • Минимальная стандартная библиотека
  21. 33 Прятать все за интерфейсы • Больше комфорта при написании

    • Платформенным инженерам проще сразу начать писать код • Менее удобно подключать к Kotlin/Native
  22. 36 Особенности конвертации enum class EventType { Create, AddText, Commit,

    Unknown; fun plain(): String { when (this) { Create -> return@plain "CREATE" AddText -> return@plain "ADD_TEXT" Commit -> return@plain "COMMIT" else -> { return@plain "UNKNOWN" } } } }
  23. 37 Особенности конвертации __attribute__((objc_subclassing_restricted)) @interface KnEventType : KnStdlibEnum + (instancetype)alloc

    __attribute__((unavailable)); + (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable)); @property (class, readonly) KnEventType *create; @property (class, readonly) KnEventType *addtext; @property (class, readonly) KnEventType *commit; @property (class, readonly) KnEventType *unknown; - (instancetype)initWithName:(NSString *)name ordinal:(int32_t)ordinal __attribute__((swift_name("init(name:ordinal:)"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable)); - (NSString *)plain __attribute__((swift_name("plain()"))); - (int32_t)compareToOther:(KnEventType *)other __attribute__((swift_name("compareTo(other:)"))); @end;
  24. 38 Особенности конвертации open class KnEventType : KnStdlibEnum { open

    class var create: KnEventType { get } open class var addtext: KnEventType { get } open class var commit: KnEventType { get } open class var unknown: KnEventType { get } open func plain() -> String open func compareTo(other: KnEventType) -> Int32 }
  25. 40 Особенности конвертации sealed class Result<out V : Any, out

    E : Exception> { abstract operator fun component1(): V? abstract operator fun component2(): E? inline fun <X> fold(success: (V) -> X, failure: (E) -> X): X = when (this) { is Success -> success(this.component1) is Failure -> failure(this.component2) } abstract fun get(): V class Success<out V : Any, out E : Exception>(val value: V) : Result<V, E>() { override fun component1(): V? = component1 override fun component2(): E? = null override fun get(): V = component1 } class Failure<out V : Any, out E : Exception>(val error: E) : Result<V, E>() { override fun component1(): V? = null override fun component2(): E? = component2 override fun get(): V = throw component2 fun getException(): E = component2 } }
  26. 41 Особенности конвертации open class KnResult : KotlinBase { open

    func component1() -> Any? open func component2() -> KnStdlibException? open func fold(success: @escaping (Any) -> Any?, failure: @escaping (KnStdlibException) -> Any?) -> Any? open func get() -> Any } open class KnResultSuccess : KnResult { public init(value: Any) open var value: Any { get } } open class KnResultFailure : KnResult { public init(error: KnStdlibException) open func getException() -> KnStdlibException open var error: KnStdlibException { get } }
  27. 45 Moya.swift public protocol TargetType { /// The target's base

    `URL`. var baseURL: URL { get } /// The path to be appended to `baseURL` to form the full `URL`. var path: String { get } /// The HTTP method used in the request. var method: Moya.Method { get } /// The type of HTTP task to be performed. var task: Task { get } /// The headers to be used in the request. var headers: [String: String]? { get } }
  28. 46 kMoya.kt interface TargetType { /// The target's base URL.

    val baseURL: String /// The path to be appended to `baseURL` to form the full URL. val path: String /// The HTTP method used in the request. val method: Method /// The type of HTTP task to be performed. val task: NetworkTask /// The headers to be used in the request. val headers: Map<String, String>? }
  29. 49 kMoyaTask.kt interface Task { val data: Data? } sealed

    class NetworkTask: Task { class RequestPlain: NetworkTask() { override val data: Data? get() = null } }
  30. 50 kMoyaTask.kt interface Task { val data: Data? } sealed

    class NetworkTask: Task { class RequestPlain: NetworkTask() { override val data: Data? get() = null } class RequestEncodable(val input: Encodable): NetworkTask() { override val data: Data? get() = input.encode() } }
  31. 51 ApiProvider.kt class ApiProvider<Target: TargetType>(val platform: Platform) { fun <ResultType:

    Any> request( target: Target, decoder: Decoder<ResultType>, completion: (Result<ResultType, NetworkError>) -> Unit) { val url = this.platform.createURLFromString(target.baseURL + target.path) ?: return val success = { res: Data -> val obj: ResultType = decoder.decode(res) completion(Result.Success(obj)) } val err = { error: NetworkError -> completion(Result.Failure(error)) } this.platform.request(url, target.method, target.task.data, success, err) } }
  32. 52 Platform.kt interface Platform { fun createURLFromString(string: String): URL? fun

    request(url: URL, method: Method, data: Data?, success: (Data) -> Unit, error: (NetworkError) -> Unit) } interface URL { } interface Data { } interface Decoder<Type> { fun decode(data: Data): Type } interface Encodable { fun encode(): Data }
  33. 53 CocoaheadsAPI.kt sealed class CocoaheadsAPI(override val baseURL: String) : TargetType

    { class EventList(baseURL: String) : CocoaheadsAPI(baseURL) { override val path: String get() = "events/index" override val method: Method get() = Method.POST override val task: NetworkTask get() = NetworkTask.RequestPlain() override val headers: Map<String, String>? get() = null } }
  34. 54 Usage.swift lazy var api: KnMoyaApiProvider = { let p

    = IOSPlatform() return KnMoyaApiProvider(platform: p) }()
  35. 55 Usage.swift func requestEventList() { self.api.request( target: KnMoyaCocoaheadsAPIEventList(baseURL: self.url), decoder:

    Decoder<[EventPlainObject]>()) { r -> KnMoyaStdlibUnit in r.success() { (res: Any) -> KnMoyaStdlibUnit in guard let events = res as? [EventPlainObject] else { return KnMoyaStdlibUnit() } // .. return KnMoyaStdlibUnit() } r.failure() { (err) -> KnMoyaStdlibUnit in // .. return KnMoyaStdlibUnit() } return KnMoyaStdlibUnit() } }
  36. 59 Минусы • Beta • Придется использовать сабсет языка •

    Инструментарий страдает • Отсутствие биткода (ведется работа)
  37. 60 Официальный гитхаб https://github.com/JetBrains/kotlin-native Марчин Москала – MVP подход https://blog.kotlin-academy.com/architecture-for-

    multiplatform-development-in-kotlin-cc770f4abdfd Приходите на AppsConf 2018, у нас будет доклад от технического руководителя проекта Kotlin/Native – Николая Иготти Тут можно узнать больше: