8

My main goal is to embed a GIF/MP4 file in a view in a HStack/VStack using SwiftUI. I understand the code needs to conform to the 'Representable' protocols. My first attempt at doing this is below:

import SwiftUI
import AVKit

struct GIF : UIViewControllerRepresentable {

    let url_name: String

    func makeUIViewController(context: UIViewControllerRepresentableContext<GIF>) -> AVPlayerViewController {
        return AVPlayerViewController()
    }

    func updateUIViewController(_ uiViewController: AVPlayerViewController, context: UIViewControllerRepresentableContext<GIF>) {
        let url = URL(string: url_name)!
        let player = AVPlayer(url: url)
        let vc = AVPlayerViewController()
        vc.player = player
//PROBLEM
        self.present(vc, animated: true){
            vc.player?.play()
        }
    }
}

The problem is that I don't think 'self' makes any sense here and we need to refer to a view. How would we do this? We can't just create a view in a story board as I want to integrate the view controller with SwiftUI.

Any help would be appreciated.

P.S. This is my first iOS app so if I'm missing something very obvious here please try to be kind!

Gene Z. Ragan
  • 2,643
  • 2
  • 31
  • 41
Vedant
  • 339
  • 4
  • 10
  • I don't use `AVKit`(?) but it looks like you're on the right track. Yes, you'll need to create a `UIViewControllerRepresentable`. And don't forget, to `SwiftUI`, it merely a `View`. I've done this for `UIImagePickerController`, `UIActivityViewController` and `MTKView` (yes, I needed to wrap this into a `UIViewController` for the delegate methods. You are doing *exactly* what I needed to do with the activity view controller - wrap it in a VC that executes `present`. Kludgy? Definitely. But remember, we're barely into beta 3 of version 1. –  Jul 08 '19 at 19:16
  • Final thoughts after reading your P.S. Why have you chosen `SwiftUI`? Sure, it's "where the puck is headed". But don't think that `UIKit` will be deprecated anytime soon. (Maybe in a decade. Seriously.) There's a ton of examples to do what you want in a `UIKit` app. Also, **do not** overlook that all `SwiftUI` apps will require that OS version coming out this fall. Since this is your first iOS app, you might want to retreat from the "bleeding edge". –  Jul 08 '19 at 19:19
  • I agree with @dfd. To not lose interest in developing in Swift, you can just try UIKit, where there are tons of working examples :) – J. Doe Jul 08 '19 at 19:35
  • Possible duplicate of [How to show my AVPlayer in a VStack with SwiftUI](https://stackoverflow.com/questions/56822943/how-to-show-my-avplayer-in-a-vstack-with-swiftui) – Bogdan Farca Jul 09 '19 at 07:20
  • Thanks for all the support. As to why I chose SwiftUI - I just thought it would be easier to use than UIKit however I now realise that perhaps its worth sticking with UIKit until SwiftUI is more developed and more community support exists for it. – Vedant Jul 09 '19 at 09:23
  • @dfd Sorry, still slightly confused as to how I should execute – Vedant Jul 09 '19 at 14:57
  • #1 Let me start with the second comment - I only know that (1) you are a "new contributor" here and (2) this is your first iOS app. Taken together I *don't* know if this is also your (a) first use of Xcode and (b) Apple frameworks and Swift. If so, I strongly recommend creating an iOS app using Xcode 10, `UIKit`, and `AVKit` first - there's quite a few examples that can guide you through everything. Once you have that working, then you can move to `SwiftUI`, which will require that a user has iOS 13 (that will likely have about 80% adoption in about one year after release). –  Jul 09 '19 at 16:31
  • #2 As for my first comment, I'm working on a `SwiftUI` app and (currently) need to move three `UIKit` classes into it as `UIViewControllerRepresentable` because of how beta things are. One, `UIActivityViewController`, (1) doesn't exist yet in SwiftUI and (2) is commonly used in UIKit through a "share" button tap that uses a `present`, just like your `AVPlayerViewController` does. For a specific reason(iPads require a `sourceView`), I created a "wrapper VC that presents and is that `sourceView`. https://stackoverflow.com/questions/56819360/swiftui-exporting-or-sharing-files/56828100#56828100 –  Jul 09 '19 at 16:41
  • #3 I think you're on the right track... if you really do want to move forward in `SwiftUI`, understanding what that means, then yes, `UIViewControllerRepresentable` is likely how you should proceed. Look at the question I posted. So far, I haven't run across *anybody* using `updateUIViewController` - not even Apple in WWDC. Write what you need in `UIKit` first (and yes, even in a `UIKit` project. Then move that code into a `SwiftUI project (probably as a `UIViewController` subclass). Then write your `SwiftUI` representable with whatever you need to use the `UIKit` code. Hope this helps! –  Jul 09 '19 at 16:47
  • Ah of course, thank you. Yes you're right in that this is my first time touching any of Apple's frameworks. This AV component is the last little piece for my current app so as soon as this is complete I think I'll switch to UIKit for my next app. Thanks for all your advice and help - I appreciate it! – Vedant Jul 09 '19 at 19:14
  • This was just released - they release one video a week an every other one if free (with the other for subscribers at US$9 a month) so I'm not sure which this is, but I think this might be of great help to you: https://talk.objc.io/episodes/S01E161-integrating-uikit-components –  Jul 17 '19 at 14:06
  • You can use this tutorial on medium-> https://medium.com/flawless-app-stories/avplayer-swiftui-part-5-videoplayer-is-here-e7821a0fd4a9 , I used this to get videos working. The part 5 shows the SwiftUI 2.0 update with VideoView. I tried it, couldn't get it work, but I think by the time it comes out of beta it will start working. Part 1-4 are UIKit based and work very well. – thenakulchawla Jul 08 '20 at 20:54

1 Answers1

1

it's easy to wrap old AVPlayerViewController

import AVKit
import SwiftUI

struct AVPlayerView: UIViewControllerRepresentable {
@Binding var videoURL: URL?

private var player: AVPlayer? {
    guard let url = videoURL else {
        return nil
    }
    return AVPlayer(url: url)
}

func updateUIViewController(_ playerController: AVPlayerViewController, context: Context) {
    playerController.player = player
    playerController.player?.play()
}

func makeUIViewController(context: Context) -> AVPlayerViewController {
    AVPlayerViewController()
}
}

but if ur target is equal or higher than 14 u can use VideoPlayer component from swiftui without any wrappers

import SwiftUI
import AVKit

struct UrView: View {
    var body:  some  View {
         VideoPlayer(
             player: AVPlayer(url: URL(string: "{ur url}"))
         )
    }
}
alexis
  • 31
  • 5