Skip to content

Commit 1a3a37b

Browse files
committed
Update README for iOS target introduction
1 parent fc147c0 commit 1a3a37b

File tree

1 file changed

+64
-4
lines changed

1 file changed

+64
-4
lines changed

README.md

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
The coverage report excludes code not intended to be covered.
1111

12-
This avoids the [“broken window” effect](https://blog.codinghorror.com/the-broken-window-theory/): whether coverage is at 43% or 56%, its perceived as equally low—so efforts to improve it are often dismissed. In contrast, high or near-100% coverage is seen as achievable and worth tracking.
12+
This avoids the [“broken window” effect](https://blog.codinghorror.com/the-broken-window-theory/): whether coverage is at 43% or 56%, it's perceived as equally low—so efforts to improve it are often dismissed. In contrast, high or near-100% coverage is seen as achievable and worth tracking.
1313

1414
Refer to the root project's [`build.gradle.kts`](build.gradle.kts#L55-L90) for details.
1515

@@ -36,13 +36,16 @@ Refer to the root project's [`build.gradle.kts`](build.gradle.kts#L55-L90) for d
3636

3737
[**Taskfolio**](https://opatry.github.io/taskfolio) is an Android task management app built using [Google Tasks API](https://developers.google.com/tasks/reference/rest). Developed to demonstrate my expertise in modern Android development, it highlights my skills in architecture, UI design with Jetpack Compose, OAuth authentication, and more—all packaged in a sleek, user-friendly interface.
3838

39-
> I set out to revisit the classical TODO app, local-first syncing with Google Tasks—aiming for an <abbr title="Minimum Viable Experience">MVE</abbr> in 2 weeks, focusing on the 80/20 rule to nail the essentials.
39+
> I set out to revisit the classical TODO app, 'local-first' syncing with Google Tasks—aiming for an <abbr title="Minimum Viable Experience">MVE</abbr> in 2 weeks, focusing on the 80/20 rule to nail the essentials.
4040
4141
| ![](assets/screens/task_lists_light.png) | ![](assets/screens/groceries_light.png) | ![](assets/screens/add_task_light.png) | ![](assets/screens/home_dark.png) |
4242
| --------------------------------------- |--------------------------------------- | ---------------------------------- | ---------------------------------- |
4343

4444
[![Taskfolio on Play Store](assets/GetItOnGooglePlay_Badge_Web_color_English.png)](https://play.google.com/store/apps/details?id=net.opatry.tasks.app)
4545

46+
> [!NOTE]
47+
> The application is also available as a desktop (Jvm) application and an iOS application as well (using [Compose Multi Platform (aka CMP)](https://www.jetbrains.com/compose-multiplatform/) as UI Toolkit).
48+
4649
## 🎯 Project intentions
4750

4851
- [x] Showcase my expertise in Android application development
@@ -76,8 +79,9 @@ I do not aim to implement advanced features beyond what is supported by the Goog
7679

7780
## 🛠️ Tech stack
7881

79-
- [Kotlin](https://kotlinlang.org/), [Multiplatform (aka KMP)](https://kotlinlang.org/docs/multiplatform.html) (currently Desktop & Android are supported)
80-
- iOS wasn’t initially planned, but I bootstrapped a [PR to evaluate the feasibility of the iOS target]((https://github.com/opatry/taskfolio/pull/269)). It turned out to be quite achievable and just needs some polishing.
82+
- [Kotlin](https://kotlinlang.org/), [Multiplatform (aka KMP)](https://kotlinlang.org/docs/multiplatform.html)
83+
- Android and Desktop are fully supported.
84+
- iOS wasn't initially planned, but a draft version is available (use it at your own risks, there might be dragons 🐉).
8185
- Web is not planned any time soon (contribution are welcome 🤝)
8286
- [Kotlin coroutines](https://kotlinlang.org/docs/reference/coroutines/coroutines-guide.html)
8387
- [Ktor client](https://ktor.io/) (+ [Kotlinx serialization](https://kotlinlang.org/docs/serialization.html))
@@ -123,6 +127,9 @@ I do not aim to implement advanced features beyond what is supported by the Goog
123127
- The Desktop application (thin layer fully reusing `:tasks-app-shared`)
124128
- [`:tasks-app-android`](tasks-app-android) <span style="color: #66FF00;">■■■■■■■■</span>□□ 80%
125129
- The Android application (thin layer fully reusing `:tasks-app-shared`)
130+
- [`:tasks-app-ios/Taskfolio`](tasks-app-ios/Taskfolio) <span style="color: #33FF00;">■■■■■■■■■</span>□ 90%
131+
- The iOS application (thin layer fully reusing `:tasks-app-shared`)
132+
- Xcode project, written in Swift
126133
- [`website/`](website) <span style="color: #00FF00;">■■■■■■■■■■</span> 100%
127134
- The [static site](https://opatry.github.io/taskfolio/) presenting the project
128135
- Made with [Jekyll](https://jekyllrb.com/) and served by [Github pages](https://pages.github.com/)
@@ -177,6 +184,59 @@ When clicking on it, it will open a new window with the hot reload status.
177184
![](assets/compose-hot-reload-console.png)
178185
</details>
179186

187+
## 🍎 Build for iOS target
188+
189+
The support of iOS works more or less _as-is_ and gets the job done. It's provided without guarantees, use at your own risk.
190+
Feedback and contributions are welcome though 🤝.
191+
192+
> [!NOTE]
193+
> iOS support is _opt-in_ and disabled by default to avoid unnecessary time and disk usage during the initial Gradle sync when the iOS target isn't required.
194+
> You can enable it by setting `ios.target` Gradle property to `all`, `simulator` or `device` from either `local.properties` or CLI using `-P`.
195+
> When building from Xcode, it automatically sets `-Pios.target=simulator` based on `Config.xcconfig`.
196+
197+
<details>
198+
<summary>See details…</summary>
199+
200+
You can build the `:tasks-app-shared` code for iOS using Gradle (to check if evertyhing compiles on Kotlin side):
201+
202+
```bash
203+
./gradlew tasks-app-shared:linkDebugFrameworkIosSimulatorArm64 -Pios.target=simulator
204+
```
205+
206+
For full XCFramework build (to be consumed by the iOS application), you'll have to rely on `xcodebuild` (or build directly from Xcode):
207+
208+
```bash
209+
cd tasks-app-ios
210+
IOS_TARGET=simulator xcodebuild -project Taskfolio.xcodeproj \
211+
-scheme Taskfolio \
212+
-sdk iphonesimulator \
213+
-arch arm64 \
214+
-configuration Debug \
215+
build \
216+
CODE_SIGNING_ALLOWED=NO \
217+
CODE_SIGN_IDENTITY="" \
218+
CODE_SIGNING_REQUIRED=NO
219+
```
220+
This triggers the `:tasks-app-shared:embedAndSignAppleFrameworkForXcode` Gradle task under the hood.
221+
222+
For Xcode integration, it's recommended to install the [Xcode Kotlin plugin](https://touchlab.co/xcodekotlin):
223+
224+
```bash
225+
brew install xcode-kotlin
226+
xcode-kotlin install
227+
```
228+
229+
When you update Xcode, you'll have to sync the plugin:
230+
231+
```bash
232+
xcode-kotlin sync
233+
```
234+
235+
If you want to debug the Kotlin code from Xcode, you'll have to add the needed source sets in Xcode:
236+
Add Group > Add folders as **reference** > `tasks-app-shared/{commonMain,iosMain}` (or any other module you want to debug).
237+
If you properly installed the Xcode Kotlin plugin, you'll be able to set a breakpoint in the Kotlin code and see syntax coloring as well.
238+
</details>
239+
180240
## ⚖️ License
181241

182242
```

0 commit comments

Comments
 (0)