Using WKInterfaceInlineMovie in SwiftUI or WatchKit

I’m working on a project where I’ve to loop and autoplay a video every-time the WKInterfaceController is shown on the watch screen.

To accomplish this, I used WKInterfaceInlineMovie. It is an interface element that displays a video’s poster image and supports inline playing of the video.

SwiftUI

I initially wrote this article for WatchKit, but my friend asked for an example in SwiftUI, so here’s a small one.

To use a WatchKit component in SwiftUI, we go back to the bridge that is WKInterfaceObjectRepresentable. This protocol requires us to make an interface object and update it.

From the documentation, we make an object by initializing a WKInterfaceInlineMovie. For our requirement, we loop the video, set the URL for it, and play it from the beginning in the update method.

And that’s it! You can use this view by providing it the URL. Here’s the full sample code for you to go through.

struct ContentView: View {
    let path = Bundle.main.path(forResource: "SampleVideo", ofType: "mp4")

    var body: some View {
        if let path = path {
            MovieView(movieURL: URL(fileURLWithPath: path))
        }
    }
}

struct MovieView: WKInterfaceObjectRepresentable {
    var movieURL: URL

    func makeWKInterfaceObject(context: Context) -> WKInterfaceInlineMovie {
        .init()
    }

    func updateWKInterfaceObject(_ movie: WKInterfaceInlineMovie, context: Context) {
        movie.setLoops(true)
        movie.setMovieURL(movieURL)
        movie.playFromBeginning()
    }
}

WatchKit

The requirement is simple. Create an IBOutlet for WKInterfaceInlineMovie, set the video URL in awake(withContext:), set loops to true, and play it from the beginning.

@IBOutlet weak var video: WKInterfaceInlineMovie!

This approach worked for the first time it opened the screen, but wouldn’t work afterwards.

I added it in willActivate() but it still wasn’t working. I realised that this method wasn’t the correct place to set/play the movie after reading the documentation for it.

The system calls this method when it is getting ready to display your interface controller. Use this method to perform last minute tasks required to ensure your content is up to date. Do not use this method to perform the initial setup of your interface. Your interface should be mostly initialised and ready to use by the time this method is called.

The best place to set the movie ended up in didAppear(). From the documentation,

WatchKit calls this method shortly after the interface controller’s contents appear onscreen. Use this method to configure animations or other interface-related tasks.

override func didAppear() {
    video.setAutoplays(true)
    video.setMovieURL(movieURL)
    video.playFromBeginning()
}

And voila, the video plays every single time the view appears!