Skip to content

Commit 603a747

Browse files
authored
update: new SKIE version and some freshening up (#532)
1 parent bdb4fac commit 603a747

File tree

6 files changed

+54
-61
lines changed

6 files changed

+54
-61
lines changed

topics/multiplatform-onboard/multiplatform-create-first-app.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ The common source set contains shared code that can be used across multiple targ
8181
It's designed to contain code that is platform-independent. If you try to use platform-specific APIs in the common source set,
8282
the IDE will show a warning:
8383

84-
1. Open the `shared/src/commonMain/kotlin/com/jetbrains/greeting/greetingkmp/Greeting.kt` file
84+
1. Open the `shared/src/commonMain/.../Greeting.kt` file
8585
where you can find an automatically generated `Greeting` class with a `greet()` function:
8686

8787
```kotlin
@@ -94,23 +94,22 @@ the IDE will show a warning:
9494
}
9595
```
9696

97-
2. Add a bit of variety to the greeting. Import `kotlin.random.Random` from the Kotlin standard library.
98-
This is a multiplatform library that works on all platforms and is included automatically as a dependency.
99-
3. Update the shared code with the `reversed()` call from the Kotlin standard library to reverse the text:
97+
2. Let's add a bit of variety to the greeting.
98+
Update the shared code with randomization and the `reversed()` call from the Kotlin standard library to reverse the text:
10099
101100
```kotlin
102-
import kotlin.random.Random
103-
104101
class Greeting {
105102
private val platform: Platform = getPlatform()
106103
107104
fun greet(): String {
105+
//
108106
val firstWord = if (Random.nextBoolean()) "Hi!" else "Hello!"
109107
110108
return "$firstWord Guess what this is! > ${platform.name.reversed()}!"
111109
}
112110
}
113111
```
112+
3. Import the `kotlin.random.Random` class following the IDE's suggestion.
114113

115114
Writing the code only in common Kotlin has obvious limitations because it can't use any platform-specific functionality.
116115
Using interfaces and the [expect/actual](multiplatform-connect-to-apis.md) mechanism solves this.

topics/multiplatform-onboard/multiplatform-dependencies.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,24 +54,24 @@ multiplatform support, is the most convenient way to work with dates in your sha
5454
```kotlin
5555
kotlin {
5656
//...
57-
sourceSets
58-
languageSettings.optIn("kotlin.time.ExperimentalTime")
57+
sourceSets {
58+
all { languageSettings.optIn("kotlin.time.ExperimentalTime") }
59+
5960
commonMain.dependencies {
60-
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.7.1")
61+
implementation("org.jetbrains.kotlinx:kotlinx-datetime:%dateTimeVersion%")
6162
}
6263
}
6364
}
6465
```
6566

66-
3. Click the **Sync Gradle Changes** button to synchronize Gradle files: ![Synchronize Gradle files](gradle-sync.png){width=50}
67-
4. In `shared/src/commonMain/kotlin`, create a new file, `NewYear.kt`, in the project directory where your `Greeting.kt` file is located.
67+
3. Select the **Build | Sync Project with Gradle Files** menu item
68+
or click the **Sync Gradle Changes** button in the build script editor to synchronize Gradle files: ![Synchronize Gradle files](gradle-sync.png){width=50}
69+
4. Right-click the `shared/src/commonMain/.../greetingkmp` directory and select **New | Kotlin Class/File** to create a new file, `NewYear.kt`.
6870
5. Update the file with a short function that calculates
69-
the number of days from today until the New Year using the `date-time` date arithmetic:
71+
the number of days from today until the New Year using the `datetime` date arithmetic:
7072

7173
```kotlin
72-
import kotlinx.datetime.*
73-
import kotlin.time.Clock
74-
74+
@OptIn(ExperimentalTime::class)
7575
fun daysUntilNewYear(): Int {
7676
val today = Clock.System.todayIn(TimeZone.currentSystemDefault())
7777
val closestNewYear = LocalDate(today.year + 1, 1, 1)
@@ -80,8 +80,8 @@ multiplatform support, is the most convenient way to work with dates in your sha
8080

8181
fun daysPhrase(): String = "There are only ${daysUntilNewYear()} days left until New Year! 🎆"
8282
```
83-
84-
6. In `Greeting.kt`, update the `Greeting` class to see the result:
83+
6. Add all necessary imports as suggested by the IDE.
84+
7. In the `Greeting.kt` file, update the `Greeting` class to see the result:
8585

8686
```kotlin
8787
class Greeting {
@@ -95,7 +95,7 @@ multiplatform support, is the most convenient way to work with dates in your sha
9595
}
9696
```
9797

98-
7. To see the results, re-run your **composeApp** and **iosApp** configurations from IntelliJ IDEA:
98+
8. To see the results, re-run your **composeApp** and **iosApp** configurations from IntelliJ IDEA:
9999

100100
![Updated mobile multiplatform app with external dependencies](first-multiplatform-project-3.png){width=500}
101101

topics/multiplatform-onboard/multiplatform-update-ui.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,23 @@ The `composeApp` module contains an Android application, defines its main activi
2727

2828
Make some changes and see how they are reflected in the UI:
2929

30-
1. Navigate to the `App.kt` file in `composeApp/src/androidMain/kotlin`.
30+
1. Navigate to the `App.kt` file in the `composeApp/src/androidMain/.../greetingkmp` directory.
3131
2. Find the `Greeting` class invocation. Select the `greet()` function, right-click it, and select **Go To** | **Declaration or Usages**.
3232
You'll see that it's the same class from the `shared` module you edited in the previous step.
33-
3. In the `Greeting.kt` file, update the `greet()` function:
33+
3. In the `Greeting.kt` file, update the `Greeting` class so that the `greet()` function returns a list of strings:
3434

3535
```kotlin
36-
import kotlin.random.Random
36+
class Greeting {
3737

38-
fun greet(): List<String> = buildList {
39-
add(if (Random.nextBoolean()) "Hi!" else "Hello!")
40-
add("Guess what this is! > ${platform.name.reversed()}!")
38+
private val platform: Platform = getPlatform()
39+
40+
fun greet(): List<String> = buildList {
41+
add(if (Random.nextBoolean()) "Hi!" else "Hello!")
42+
add("Guess what this is! > ${platform.name.reversed()}!")
43+
}
4144
}
4245
```
4346

44-
Now it returns a list of strings.
45-
4647
4. Go back to the `App.kt` file and update the `App()` implementation:
4748

4849
```kotlin
@@ -82,8 +83,8 @@ framework. The UI of the app is written in Swift.
8283

8384
Implement the same changes as in the Android app:
8485

85-
1. In IntelliJ IDEA, find the `iosApp` folder at the root of your project in the **Project** tool window.
86-
2. Open the `ContentView.swift` file, right-click the `Greeting().greet()` call, and select **Go To** | **Definition**.
86+
1. In IntelliJ IDEA, find the `iosApp/iosApp` folder at the root of your project in the **Project** tool window.
87+
2. Open the `iosApp/ContentView.swift` file, right-click the `Greeting().greet()` call, and select **Go To** | **Definition**.
8788

8889
You'll see the Objective-C declarations for the Kotlin functions defined in the `shared` module. Kotlin types are
8990
represented as Objective-C types when used from Objective-C/Swift. Here the `greet()` function

topics/multiplatform-onboard/multiplatform-upgrade-app.md

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ You'll need to add the following multiplatform libraries in your project:
4242
### kotlinx.coroutines
4343

4444
To add `kotlinx.coroutines` to your project, specify a dependency in the common source set. To do so, add the following
45-
line to the `build.gradle.kts` file of the shared module:
45+
line to the `shared/build.gradle.kts` file:
4646

4747
```kotlin
4848
kotlin {
@@ -62,8 +62,7 @@ of `kotlinx.coroutines`.
6262
### kotlinx.serialization
6363

6464
To use the `kotlinx.serialization` library, set up a corresponding Gradle plugin.
65-
To do that, add the following line to the existing `plugins {}` block at the very beginning of the `build.gradle.kts` file
66-
in the shared module:
65+
To do that, add the following line to the existing `plugins {}` block at the very beginning of the `shared/build.gradle.kts` file:
6766

6867
```kotlin
6968
plugins {
@@ -116,7 +115,7 @@ get the list of all launches from the **v4/launches** endpoint.
116115

117116
### Add a data model
118117

119-
In the `shared/src/commonMain/kotlin/.../greetingkmp` directory, create a new `RocketLaunch.kt` file
118+
In the `shared/src/commonMain/.../greetingkmp` directory, create a new `RocketLaunch.kt` file
120119
and add a data class which stores data from the SpaceX API:
121120

122121
```kotlin
@@ -143,13 +142,13 @@ data class RocketLaunch (
143142

144143
### Connect HTTP client
145144

146-
1. In the `shared/src/commonMain/kotlin/.../greetingkmp` directory, create a new `RocketComponent` class.
145+
1. In the `shared/src/commonMain/.../greetingkmp` directory, create a new `RocketComponent` class.
147146
2. Add the `httpClient` property to retrieve rocket launch information through an HTTP GET request:
148147

149148
```kotlin
150-
import io.ktor.client.*
151-
import io.ktor.client.plugins.contentnegotiation.*
152-
import io.ktor.serialization.kotlinx.json.*
149+
import io.ktor.client.HttpClient
150+
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
151+
import io.ktor.serialization.kotlinx.json.json
153152
import kotlinx.serialization.json.Json
154153

155154
class RocketComponent {
@@ -185,8 +184,8 @@ data class RocketLaunch (
185184
4. Call the `httpClient.get()` function to retrieve information about rocket launches:
186185
187186
```kotlin
188-
import io.ktor.client.request.*
189-
import io.ktor.client.call.*
187+
import io.ktor.client.request.get
188+
import io.ktor.client.call.body
190189
191190
class RocketComponent {
192191
// ...
@@ -222,11 +221,13 @@ data class RocketLaunch (
222221
```kotlin
223222
import kotlinx.datetime.TimeZone
224223
import kotlinx.datetime.toLocalDateTime
224+
import kotlin.time.ExperimentalTime
225225
import kotlin.time.Instant
226226

227227
class RocketComponent {
228228
// ...
229229

230+
@OptIn(ExperimentalTime::class)
230231
private suspend fun getDateOfLastSuccessfulLaunch(): String {
231232
val rockets: List<RocketLaunch> =
232233
httpClient.get("https://api.spacexdata.com/v4/launches").body()
@@ -325,18 +326,7 @@ Now that the application is becoming more complex, it's time to introduce a view
325326
called `MainActivity`. It invokes the `App()` function that implements the UI.
326327
The view model will manage the data from the activity and won't disappear when the activity undergoes a lifecycle change.
327328
328-
1. Add the following dependencies to your `composeApp/build.gradle.kts` file:
329-
330-
```kotlin
331-
androidMain.dependencies {
332-
// ...
333-
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2")
334-
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.6.2")
335-
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2")
336-
}
337-
```
338-
339-
2. In the `composeApp/src/androidMain/kotlin/com/jetbrains/greeting/greetingkmp` directory,
329+
1. In the `composeApp/src/androidMain/.../greetingkmp` directory,
340330
create a new `MainViewModel` Kotlin class:
341331
342332
```kotlin
@@ -349,7 +339,7 @@ The view model will manage the data from the activity and won't disappear when t
349339
350340
This class extends Android's `ViewModel` class, which ensures the correct behavior regarding lifecycle and configuration changes.
351341

352-
3. Create a `greetingList` value of the [StateFlow](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-state-flow/)
342+
2. Create a `greetingList` value of the [StateFlow](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-state-flow/)
353343
type and its backing property:
354344

355345
```kotlin
@@ -365,7 +355,7 @@ The view model will manage the data from the activity and won't disappear when t
365355
* `StateFlow` here extends the `Flow` interface but has a single value or state.
366356
* The private backing property `_greetingList` ensures that only clients of this class can access the read-only `greetingList` property.
367357

368-
4. In the `init` function of the View Model, collect all the strings from the `Greeting().greet()` flow:
358+
3. In the `init` function of the View Model, collect all the strings from the `Greeting().greet()` flow:
369359

370360
```kotlin
371361
import androidx.lifecycle.viewModelScope
@@ -388,7 +378,7 @@ The view model will manage the data from the activity and won't disappear when t
388378
Since the `collect()` function is suspended, the `launch` coroutine is used within the view model's scope.
389379
This means that the launch coroutine will run only during the correct phases of the view model's lifecycle.
390380

391-
5. Inside the `collect` trailing lambda, update the value of `_greetingList` to append the collected `phrase` to the list of phrases in `list`:
381+
4. Inside the `collect` trailing lambda, update the value of `_greetingList` to append the collected `phrase` to the list of phrases in `list`:
392382

393383
```kotlin
394384
import kotlinx.coroutines.flow.update
@@ -418,6 +408,7 @@ The view model will manage the data from the activity and won't disappear when t
418408
import androidx.lifecycle.viewmodel.compose.viewModel
419409
420410
@Composable
411+
@Preview
421412
fun App(mainViewModel: MainViewModel = viewModel()) {
422413
MaterialTheme {
423414
val greetings by mainViewModel.greetingList.collectAsStateWithLifecycle()
@@ -664,6 +655,11 @@ plugins {
664655
}
665656
```
666657
658+
> The 0.10.6 version of SKIE latest at the moment of writing does not support the latest Kotlin.
659+
> To use it, downgrade your Kotlin version to 2.2.10 in the `gradle/libs.versions.toml` file.
660+
>
661+
{style="warning"}
662+
667663
#### Consume the flow using SKIE
668664
669665
You'll use a loop and the `await` mechanism to iterate through the `Greeting().greet()` flow and update the `greetings`

topics/overview/faq.md

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,17 +67,14 @@ this code depends on where you call the code from. Calling suspending functions
6767
documented, especially for Android. [Calling them from Swift code](https://kotlinlang.org/docs/native-arc-integration.html#completion-handlers)
6868
requires a little more work, see [KT-47610](https://youtrack.jetbrains.com/issue/KT-47610) for more details.
6969

70-
<!-- when adding SKIE back to the tutorial, add it here as well
71-
and uncomment the paragraph below -->
72-
7370
The best current approach for calling suspending functions and flows from Swift is to use plugins and libraries like
7471
[KMP-NativeCoroutines](https://github.com/rickclephas/KMP-NativeCoroutines) together
7572
with Swift's `async`/`await` or libraries like Combine and RxSwift.
7673

77-
<!-- At the moment, KMP-NativeCoroutines is the more
78-
tried-and-tested solution, and it supports `async`/`await`, Combine, and RxSwift approaches to concurrency. SKIE is easier
79-
to set up and less verbose. For instance, it maps Kotlin `Flow` to Swift `AsyncSequence` directly. Both of these libraries
80-
support the proper cancellation of coroutines. -->
74+
At the moment, KMP-NativeCoroutines is the more
75+
tried-and-tested solution, and it supports `async`/`await`, Combine, and RxSwift approaches to concurrency.
76+
SKIE can be easier to set up and is less verbose. For instance, it maps Kotlin `Flow` to Swift `AsyncSequence` directly.
77+
Both of these libraries support the proper cancellation of coroutines.
8178

8279
To learn how to use them, see [](multiplatform-upgrade-app.md).
8380

v.list

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
<var name="ktorVersion" value="3.3.1" type="string"/>
4040
<var name="dateTimeVersion" value="0.7.1" type="string"/>
4141
<var name="koinVersion" value="4.1.0" type="string"/>
42-
<var name="skieVersion" value="0.10.4" type="string"/>
42+
<var name="skieVersion" value="0.10.6" type="string"/>
4343
<var name="kmpncVersion" value="1.0.0-ALPHA-45" type="string"/>
4444
<var name="kspVersion" value="2.2.10-2.0.2" type="string"/>
4545
<var name="vanniktechPublishPlugin" value="0.34.0" type="string"/>

0 commit comments

Comments
 (0)