Enhancing iOS UI Previews: Swift UI Packages & Kotlin Multiplatform Mobile.

Thomas Kiokoβ„’
4 min readSep 10, 2024

--

Photo by Akshar Dave🌻 on Unsplash

Intro:

Remember our adventure in Going Modular β€” The Kotlin Multiplatform Way? Well, this is a continuation of that. (Sort of 😁). I say sort of because this article focuses on the Swift side of things. We will explore how creating UI components in a separate Swift package can significantly improve the development experience when working on the iOS App.

This is a blog of an ongoing series on my journey with Kotlin Multiplatform.

If you are interested in the code, here is the Pull Request. Let’s get this party started.

The KMM Preview Headache πŸ€•

While working with KMM on iOS, one of my biggest headaches is that Previews don’t load in XCode. I don’t know why XCode does not play nice with KMM. It either takes too long to load or fails. The only way to see what I am creating is by running the application. This is frustrating as it slows development time.

Enter Separate Swift Packages πŸ“¦

By relocating our UI components into a separate Swift package, we’re not just organizing our code, but we’re also unlocking a host of benefits that can significantly enhance our development experience:

  1. Functional SwiftUI Previews
  • By isolating views from the KMM framework, providing real-time UI development feedback, and improving the developer experience, we can load views faster.

2. Improved Reusability

  • Components can be easily reused across the application, leading to a more modular architecture and reducing code duplication.

3. Streamlined Testing

  • With this in place, Snapshot testing becomes a viable option for ensuring UI consistency. Coming soon. πŸ€“

4. Optimized Project Structure

  • A clear structure makes it easy to maintain and update our components.

App structure:

I ended up creating two packages:

  • SwiftUIComponents: This package contains common views used in various screens. Colors, Buttons, CardView, PosterImage etc
  • TVManiacUI: This Package includes Screen UI Views. eg. CastList, TrailerList, ShowInfoView. etc

Below is what the structure of the App looks like.

TvManiac/
β”œβ”€β”€ shared/
β”‚ └── ... (Kotlin shared code)
β”œβ”€β”€ androidApp/
β”‚ └── ... (Android-specific code)
β”œβ”€β”€ iosApp/
β”‚ β”œβ”€β”€ iosApp.xcodeproj
β”‚ β”œβ”€β”€ iosApp/
β”‚ β”‚ └── ... (iOS app-specific code)
β”‚ └── Modules/
β”‚ └── SwiftUIComponents/
β”‚ β”‚ β”œβ”€β”€ Package.swift
β”‚ β”‚ └── Sources/
β”‚ β”‚ └── SwiftUIComponents/
β”‚ β”‚ └──Components/
β”‚ β”‚ β”œβ”€β”€ BottomNavigation.swift
β”‚ β”‚ β”œβ”€β”€ HeaderContentView.swift
β”‚ β”‚ └── ...
β”‚ β”‚ β”œβ”€β”€ CollapsibleView.swift
β”‚ β”‚ β”œβ”€β”€ TrailerItemView.swift
β”‚ β”‚ └── ...
β”‚ └── TVManiacUI/
β”‚ β”œβ”€β”€ Package.swift
β”‚ └── Sources/
β”‚ └── TVManiacUI/
β”‚ └──Models/
β”‚ └── SwiftCast.swift
β”‚ └── SwiftTrailer.swift
β”‚ β”œβ”€β”€ CastListView.swift
β”‚ β”œβ”€β”€ ShowInfoView.swift
β”‚ β”œβ”€β”€ ProviderListView.swift
β”‚ └── ...

Implementing the Approach

Integrating a package in XCode is a straightforward process. These are the steps I followed:

1. Package Creation and Configuration

  • Create a new Swift package (`SwiftUIComponents`) using your preferred method (Xcode UI or Swift Package Manager CLI).
  • Configure the `Package.swift` file to specify the iOS deployment target and any necessary dependencies.

2. Component Migration

  • Migrate SwiftUI views and components from your KMP iOS project to the new package.
  • Refactor as needed to ensure components are self-contained and don’t rely on KMM-specific code.

3. Dependency Management

  • If your UI components require a specific package, use Swift Package Manager’s dependency declaration to manage package relationships. In my case, I added `SDWebImageSwiftUI` and `YouTubePlayerKit` and removed them from the main app.

4. Final Step

  • In your main iOS project, go to File > Add Packages.
  • Select `SwiftUIComponents` package.
  • (Optional) Create a new scheme and select the framework, in this case, `SwiftUIComponents.` This allows us to switch between the Main app and the UI package.

With that in place, here’s an example of how the project structure looks after implementing this approach. πŸ₯³

UI Components Preview
TvManiacUI Preview

Conclusion

I highly recommend trying this approach. It’s made my life easier, my code cleaner, and the general structure better. Next, we might add snapshot tests, a CI/CD job, and more cleanup.

Until we meet again, folks. Happy coding! ✌️

--

--