iOS용 Jetpack Compose
2023년 2월 13일 업데이트됨
암호:
https://github.com/marenovakovic/compose-ios
Jetpack Compose는 틀림없이 Android 자체가 시작된 이래로 Android 개발에 일어난 가장 크고 좋은 일입니다. Kotlin을 채택하면 바로 거기에 도달할 수 있습니다. 엔지니어링 대리석과 사용의 절대적인 기쁨입니다.
Compose를 멀티플랫폼으로 포팅하려는 Jetbrains의 노력으로 단일 코드 베이스에서 Android 및 데스크톱 앱을 빌드하는 흥미로운 용도를 볼 수 있습니다. 그러나 iOS는 어떻습니까? 그것이 가능하다는 것이 밝혀졌습니다… 비록 그렇게 부드럽지는 않지만. 이제 어떻게 하는지 단계별로 보여드리겠습니다.
전제 조건
- 뻔하지만 주목할 가치가 있습니다. MacOS에서만 이 작업을 수행할 수 있습니다. 예, Compose이지만 여전히 시뮬레이터와 같은 것이 필요합니다.
- 아키텍처 구성요소, 동반 라이브러리 등 Android 개발에서 사용했던 모든 라이브러리를 사용하지 못할 수도 있습니다. 멀티플랫폼(아직?)이 아니기 때문입니다. 하지만 대부분의 경우 Compose는 예상대로 작동합니다. iOS 지원이 아직 실험 단계이기 때문입니다 .
Compose iOS 앱용 모듈이 필요합니다. iOS 앱이 프로젝트의 유일한 모듈인 독립 실행형 앱이거나(네이티브 Android 개발을 위한 방법과 동일) KMM 프로젝트에 모듈을 하나 더 추가할 수 있습니다.
이에 대한 새 프로젝트를 생성하려면 IntelliJ IDEA의 새 프로젝트 마법사에서 Compose Multiplatform을 선택합니다.
새로 생성된 모듈/프로젝트 내에서 이 요지를 복사하여 붙여넣고 이 요지를 에 build.gradle.kts사용 합니다 .settings.gradle.kts
에 대해 설명할 몇 가지 사항입니다 build.gradle.kts.
id("ord.jetbrains.compose") version "1.3.0-rc01, 7행 및 maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")16행은 Compose Multiplatform을 앱에 추가하는 방법입니다.
다음과 같이 대상을 정의합니다.
iosX64("uikitX64") {
binaries {
executable {
entryPoint = "main"
freeCompilerArgs += listOf(
"-linker-option", "-framework", "-linker-option", "Metal",
"-linker-option", "-framework", "-linker-option", "CoreText",
"-linker-option", "-framework", "-linker-option", "CoreGraphics"
)
}
}
}
iosArm64("uikitArm64") {
binaries {
executable {
entryPoint = "main"
freeCompilerArgs += listOf(
"-linker-option", "-framework", "-linker-option", "Metal",
"-linker-option", "-framework", "-linker-option", "CoreText",
"-linker-option", "-framework", "-linker-option", "CoreGraphics"
)
freeCompilerArgs += "-Xdisable-phases=VerifyBitcode"
}
}
}
compose.experimental이제 조금 더 설명이 필요한 블록을 살펴보겠습니다 . uikit.applicationiOS 앱을 설정할 수 있습니다. bundleIdPrefix및 와 같은 것을 볼 수 있습니다 projectName. 우리 Android 개발자와 bundleIdPrefix같으며 거의 자명합니다.applicationIdprojectName
이제 deployConfiguration. Gradle 작업으로 iOS 앱을 배포/실행 중입니다. 댓글에서 볼 수 있습니다. 그것들은 iosDeployIPhone13ProDebug및 입니다 iosDeployIPadDebug. 또한 이 작업에서 앱을 실행하려는 장치를 정의합니다. 내부에서 지정하는 이름은 simulator("xxx")해당 구성에 대한 Gradle 작업을 결정하며 이름은 xxx. Gradle 작업은 iosDeployxxxDebug.
당신은 이미 그것이 무엇인지 궁금해 할 것입니다 teamId. 솔직히 말해서 완전히 확신할 수는 없지만 앱의 릴리스 버전을 빌드하는 데 필요하다고 생각합니다. 디버그는 그것 없이도 잘 실행될 것입니다. 이를 위해서는 Apple 개발자 멤버십이 필요합니다. teamId당신은 거기에서 얻을 것이다 .
Gradle 설정은 여기까지입니다. 파일 구조로 이동합시다. 내부에는 module/src생성이 필요 uikitMain/kotlin하고 그 내부에는 main.uikit.kt파일이 필요합니다. 다음과 같아야 합니다.
iosCompose내가 선택한 이름입니다. 다른 것을 선택할 수 있습니다.
내부에 main.uikit.kt다음 코드를 붙여넣습니다.
이것은 최소한의 설정이며, 보고 나면 위협적이지 않습니다. 지금은 앱이 이 요지의 43행에 작성되어 있다는 점을 제외하면 그것에 대해 아무것도 알 필요가 없습니다.
window!!.rootViewController = Application("Your Application") {
Text("Helo World, from Compose iOS app!!!")
}
이제 남은 일은 앱을 실행하는 것뿐이다. 그러나 그렇게 빠르지는 않습니다. 한 단계 더 필요합니다. Xcode의 시뮬레이터에서 iOS 앱을 실행한 적이 없는 경우에만 이 작업을 수행해야 합니다.
그리고 그것이 오늘 당신의 임무입니다.
Xcode에서 새 iOS 앱을 만들고 앱을 실행합니다. 인증서가 필요하기 때문에 필요합니다. Xcode를 설치하라는 메시지가 표시되며 login.keychain비밀번호가 필요합니다.
마지막으로 터미널을 열고 ./gradlew iosDeployIPhone13ProDebugAndroid Studio 또는 IntellijIDEA 내부의 Gradle 도구 창에서 이 작업을 실행하거나 찾습니다.
이 접근 방식은 매우 제한적이라는 점을 언급해야 합니다. 사용하려는 모든 항목은 동일한 모듈에 있어야 합니다. @Composable모듈 에서 s를 가져올 수 없었고 플랫폼 간에 s를 shared공유할 수 없습니다 . @Composable우리 모듈은 완전히 독립적이며 iOS 애플리케이션을 위한 프로젝트가 없습니다.
더 좋은 방법이 있습니다…
두 번째 접근법
지금 살펴볼 접근 방식이 훨씬 낫습니다. @Composable플랫폼 간에 s를 재사용할 수 있고 기본 iOS 애플리케이션에 액세스할 수 있습니다.
@Composable이 접근 방식의 경우 모듈 에 모든 s가 있습니다 shared.
이를 위해서는 클래식 Compose Multiplatform 설정이 필요합니다.
settings.gradle.kts
pluginManagement {
repositories {
google()
gradlePluginPortal()
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
mavenCentral()
}
}
plugins {
//trick: for the same plugin versions in all sub-modules
id("com.android.application").version("8.1.0-alpha04").apply(false)
id("com.android.library").version("8.1.0-alpha04").apply(false)
id("org.jetbrains.compose").version("1.3.0").apply(false)
kotlin("android").version("1.8.0").apply(false)
kotlin("multiplatform").version("1.8.0").apply(false)
id("org.jetbrains.kotlin.jvm") version "1.8.0" apply false
}
allprojects {
repositories {
google()
mavenCentral()
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
}
plugins {
kotlin("multiplatform")
kotlin("native.cocoapods")
id("com.android.library")
id("org.jetbrains.compose")
}
kotlin {
android()
ios()
iosSimulatorArm64()
cocoapods {
summary = "Some description for the Shared Module"
homepage = "Link to the Shared Module homepage"
version = "1.0"
ios.deploymentTarget = "14.1"
podfile = project.file("../ios/Podfile")
framework {
baseName = "shared"
isStatic = true
}
}
sourceSets {
val commonMain by getting {
dependencies {
implementation(compose.ui)
implementation(compose.foundation)
implementation(compose.material)
implementation(compose.runtime)
}
}
val androidMain by getting
val iosMain by getting {
dependsOn(commonMain)
}
val iosSimulatorArm64Main by getting {
dependsOn(iosMain)
}
}
}
android {
namespace = "com.example.compose_ios"
compileSdk = 33
defaultConfig {
minSdk = 24
targetSdk = 33
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
내부는 그것이 정의된 모듈 외부에서 볼 수 없다는 것을 의미합니다. 우리의 경우 s를 shared어떻게 공유할 것입니까 ? 우리는 각각 @Composable파일 main.android.kt과 main.ios.kt내부 shared/androidMain를 가질 것입니다. 거기에서 내부shared/iosMain s를 호출합니다 . 이와 같이: @Composable
shared/commonMain. 이것은 플랫폼 간에 공유할 실제 애플리케이션입니다.
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Scaffold
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@Composable
internal fun ExampleApplication() {
MaterialTheme {
Scaffold(
topBar = { TopAppBar { Text("Hello") } },
content = {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center,
) {
Text("From Compose!")
}
},
)
}
}
import androidx.compose.runtime.Composable
@Composable
fun Application() {
ExampleApplication()
}
import androidx.compose.ui.window.Application
import platform.UIKit.UIViewController
fun MainViewController(): UIViewController =
Application("Example Application") {
ExampleApplication()
}
//iosApp.swift
import SwiftUI
import shared
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
let mainViewController = Main_iosKt.MainViewController()
window?.rootViewController = mainViewController
window?.makeKeyAndVisible()
return true
}
}

![연결된 목록이란 무엇입니까? [1 부]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































