Building a Netflix-like app for iOS and iPadOS in #SwiftUI - a thread: Image
Two weeks ago, I wrote about my experience with building a video streaming app for @cineasterna (). The app lets people watch movies for free with their public library card. This thread will discuss how porting that app to a universal #SwiftUI app went.
Just like on tvOS, the iOS and iPadOS app (referred to as iOS from now on) is oriented around four tabs - Discover, All Movies, Search and Profile. If a logged in user has favorites, an additional Favorites tab is added. If no user is logged in, the Profile tab says Login. Image
The Discover screen is a vertical list with horizontal shelves. This caused me much headache in tvOS, where lazy stacks and grids have horrible performance. This is not true for iOS, though, where performance is amazing, so here I use stacks instead of a custom collection view. ImageImage
Movie covers are downloaded with Kingfisher, with the same configuration as the TV. I use a pre-processor that scales down images and use a disk cache. However, the stacks and grids put less constraints on image sizes than the UIKit collection view wrapper I had to use for tvOS. Image
Shelf sections are tappable and takes you to the specific list. Since I use stacks and grids instead of the UIKit collection view wrapper from tvOS, I can use navigation links for movie covers. However, due to the app design, I chose to present movies in modal sheets. Image
Navigating to a list renders it as a LazyVGrid. Here, I had layout problems, since I want to 3 covers per row for phones. This will obviously not work for larger screens, so I chose a size range instead. It looks good even on large screens, but there covers should be larger. ImageImage
Both shelves and grids lazy loads more content when they scroll to the end. This was easy to do, by looking at the movie when rendering a list item. For shelves, the movie must be the first movie in the last loaded list. For grids, it must be the last loaded movie in the list. Image
”All Movies” loads a first, unfiltered page into a lazy grid and lazy loads more content as the user scrolls. Since this is a vast data source, I added filtering options topmost. The filtering is done in custom (simple) pickers that supports optionals and multi selection. Image
”Search” has a custom-made header that replicates a native search bar, including an embedded clear button and a trailing Cancel button. Just like ”All Movies”, it presents the search result in a lazy grid and lazy loads more content as the user scrolls. Image
I adapted the movie screen from tvOS to work as a modal sheet for smaller screens. Instead of a backdrop, the movie image is now presented as a prominent header, with the most important info and some action buttons. Below, more info is displayed, together with primary actions. ImageImage
The contributor list was a breeze to build in #SwiftUI, using a scrolling HStack and a clip shape. I can’t even begin to imagine building it with a UICollectionView in UIKit. Woooops, looking at it now, I see that I accidentally added it to a padded container. Hotfix coming up 😅 Image
The video player was easy to build, by just reusing the player from the TV app and presenting it as a full screen cover. The player stores the position of each unique movie and restores it the next time that movie is played. Reaching the end resets position and closes the player.
A fun addition to this app was to build Chromecast support with the GoogleCast library. All in all, the Chromecast docs are great, the Swift sample code not swifty, the sample app badly focused at the core aspects of Chromecast and the overall developer experience not that great. ImageImage
Finally, the Profile screen is limited in design and functionality. It lets the user login, logout, switch library and get more information about the service. It also has links to support and account pages. Image
To wrap up, building this app in #SwiftUI was a lot easier than to build one for tvOS, much since I know the HIG better and that grids and stacks work better. Some views and api:s are still missing, so you still have to wrap native UIKit components, but not as much as in tvOS.
All in all, this was another fun project that I'm proud to release. @cineasterna is available on iOS and tvOS, with macOS support for M1 Macs running the iOS app. To test it, search for Cineasterna on the App Store (loans requires a Swedish library card). Thanks for reading! 👋
@daveverwer Thank you for sharing my work with the tvOS app earlier! I can confirm that the performance issues with stacks and grids are nonexistent on iOS 👍

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with Daniel Saidi

Daniel Saidi Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Too expensive? Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal Become our Patreon

Thank you for your support!

Follow Us on Twitter!