Jetpack เขียนสำหรับ iOS
อัปเดตเมื่อวันที่ 13 กุมภาพันธ์ 2023
รหัส:
https://github.com/marenovakovic/compose-ios
Jetpack Compose เป็นสิ่งที่ยิ่งใหญ่ที่สุดและดีที่สุดที่เกิดขึ้นกับการพัฒนา Android ตั้งแต่จุดเริ่มต้นของ Android เอง มันขึ้นอยู่กับการนำ Kotlin มาใช้ — หินอ่อนทางวิศวกรรมและความสุขในการใช้งานอย่างแท้จริง
ด้วยความพยายามของ Jetbrains ในการพอร์ต Compose ไปยัง Multiplatform เราเห็นการใช้งานที่น่าสนใจสำหรับการสร้างแอพ Android และเดสก์ท็อปจากฐานรหัสเดียว แต่ iOS ล่ะ? ปรากฎว่าเป็นไปได้เช่นกัน… แม้ว่าจะไม่ราบรื่นนัก ตอนนี้ฉันจะแสดงวิธีทำทีละขั้นตอน
ข้อกำหนดเบื้องต้น
- มันชัดเจน แต่น่าสังเกต คุณสามารถทำได้จาก MacOS เท่านั้น ใช่ มันคือการเขียน แต่คุณยังต้องการสิ่งต่าง ๆ เช่นโปรแกรมจำลอง
- คุณอาจใช้ไลบรารี่ทั้งหมดที่คุณคุ้นเคยจากการพัฒนา Android ของคุณไม่ได้: ส่วนประกอบสถาปัตยกรรม ไลบรารีที่ใช้ร่วมกัน ฯลฯ เนื่องจากสิ่งเหล่านี้ไม่ใช่ Multiplatform (ยัง?) แต่ส่วนใหญ่ Compose จะทำงานตามที่คุณคาดหวัง เนื่องจากการรองรับ iOS ยังอยู่ในช่วงทดลอง
คุณต้องมีโมดูลสำหรับแอปเขียน iOS อาจเป็นแอปแบบสแตนด์อโลนที่มีแอป iOS เป็นโมดูลเดียวในโครงการ (เช่นเดียวกับวิธีที่คุณใช้ในการพัฒนา Android แบบเนทีฟ) หรือคุณสามารถเพิ่มอีกหนึ่งโมดูลในโครงการ KMM ของคุณ
หากคุณต้องการสร้างโปรเจ็กต์ใหม่สำหรับสิ่งนี้ ให้เลือก เขียนหลายแพลตฟอร์ม ในตัวช่วยสร้างโปรเจ็กต์ใหม่ของ IntelliJ IDEA
ภายในโมดูล/โครงการที่สร้างขึ้นใหม่ ให้คัดลอกและวางส่วนสำคัญนี้ลงใน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.applicationให้คุณตั้งค่าแอพ iOS ของคุณ คุณเห็นสิ่งต่าง ๆเช่นbundleIdPrefixและ เป็นเหมือนนักพัฒนา Android สำหรับเราและค่อนข้างอธิบายได้ด้วยตนเองprojectNamebundleIdPrefixapplicationIdprojectName
ตอนนี้ขอย้ายไปdeployConfigurationที่ คุณกำลังปรับใช้/รันแอป iOS ของคุณด้วยงาน Gradle; คุณสามารถดูได้ในความคิดเห็น นั่นคือiosDeployIPhone13ProDebugและiosDeployIPadDebug. เรายังกำหนดอุปกรณ์ที่เราต้องการให้งานนี้เรียกใช้แอพของเรา ชื่อที่คุณระบุภายในsimulator("xxx")จะเป็นตัวกำหนดงาน Gradle ของคุณสำหรับการกำหนดค่านั้น และจะถูกตั้งชื่อด้วยxxx. งาน Gradle จะเป็นiosDeployxxxDebug.
คุณอาจสงสัยว่าคือteamIdอะไร พูดตามตรง ฉันไม่แน่ใจนัก แต่ฉันคิดว่าคุณต้องการมันเพื่อสร้างเวอร์ชันที่เผยแพร่ของแอปของคุณ การดีบักจะทำงานได้ดีหากไม่มีมัน คุณต้องเป็นสมาชิก Apple Developer คุณจะได้รับ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!!!")
}
สิ่งเดียวที่เหลือในตอนนี้คือการเรียกใช้แอป แต่ไม่เร็วนัก เราต้องการอีกหนึ่งขั้นตอน คุณจะต้องดำเนินการนี้เฉพาะในกรณีที่คุณไม่เคยเรียกใช้แอป iOS บนโปรแกรมจำลองจาก Xcode
และนั่นคืองานของคุณในวันนี้
สร้างแอป iOS ใหม่ใน Xcode และเรียกใช้แอป สิ่งนี้จำเป็นเนื่องจากคุณต้องการใบรับรอง Xcode จะแจ้งให้คุณติดตั้งซึ่งจะต้องใช้login.keychainรหัสผ่าน
และสุดท้าย เปิดเทอร์มินัลของคุณแล้วเรียกใช้./gradlew iosDeployIPhone13ProDebugหรือค้นหางานนี้ภายในหน้าต่างเครื่องมือ Gradle ภายใน Android Studio หรือ IntellijIDEA
ฉันต้องพูดถึงว่าวิธีนี้มีข้อ จำกัด อย่างมาก ทุกอย่างที่คุณต้องการใช้จะต้องอยู่ในโมดูลเดียวกัน ฉันไม่สามารถนำเข้า@Composableจากsharedโมดูลและคุณไม่สามารถแชร์@Composableระหว่างแพลตฟอร์มได้ โมดูลของเรามีอยู่ในตัวเองทั้งหมดและเราไม่มีโครงการสำหรับแอปพลิเคชัน iOS
มีวิธีที่ดีกว่า…
วิธีที่สอง
วิธีการที่เราจะดูตอนนี้ดีกว่ามาก: เราจะสามารถใช้ซ้ำ@Composableระหว่างแพลตฟอร์มและเราจะสามารถเข้าถึงแอปพลิเคชัน iOS ดั้งเดิมได้
สำหรับแนวทางนี้ เราจะมีทั้งหมดของเรา@Composableใน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
}
}
ภายในหมายความว่าจะไม่สามารถมองเห็นได้ภายนอกโมดูลที่กำหนดไว้ในกรณีของเราsharedดังนั้นเราจะแบ่งปัน@Composables อย่างไร เราจะมีไฟล์main.android.ktและmain.ios.ktภายในshared/androidMainและshared/iosMainตามลำดับ เราจะเรียกภายใน @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)