I would like to use VLCKit with SwiftUI.
why not AVPlayer ? because a some video formats are not supported.
Here is my code:
import SwiftUI
import UIKit
struct ContentView: View {
var body: some View {
NavigationView
{
VStack{
PlayerView(url: "https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8")
}
}
}
}
struct PlayerView: UIViewRepresentable {
public var url: String
let mediaPlayer = VLCMediaPlayer()
func makeUIView(context: Context) -> UIView {
let controller = UIView()
mediaPlayer.drawable = controller
let uri = URL(string: self.url)
let media = VLCMedia(url: uri!)
mediaPlayer.media = media
mediaPlayer.play()
return controller
}
func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<PlayerView>) {
}
}
This works and load the video but I would like to add playback controls (Full Screen, Play/Pause, forward, etc.).
I didn't find any documentation about this can anyone help me a bit,
Thanks
I watched this video on youtube
https://www.youtube.com/watch?v=N_u9nsXNvn4
and this
How to show my AVPlayer in a VStack with SwiftUI
Here is my demo
import SwiftUI
struct VlcPlayerDemo: UIViewRepresentable{
func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<VlcPlayerDemo>) {
}
func makeUIView(context: Context) -> UIView {
return PlayerUIView(frame: .zero)
}
}
class PlayerUIView: UIView, VLCMediaPlayerDelegate {
private let mediaPlayer = VLCMediaPlayer()
override init(frame: CGRect) {
super.init(frame: frame)
let url = URL(string: "rtsp://xxxxx")!//replace your resource here
mediaPlayer.media = VLCMedia(url: url)
mediaPlayer.delegate = self
mediaPlayer.drawable = self
mediaPlayer.play()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
}
}
struct VlcPlayerDemo_Previews: PreviewProvider {
static var previews: some View {
VlcPlayerDemo()
}
}
Related
I am working on a video editor app where I need a trimmer for the video. So I found this package. Now When I'm trying to show the TrimView,but it's not showing up on my SwiftUI view.
This is my View Controller Representable
final class TrimView: UIViewControllerRepresentable{
let player: AVPlayer
init(player: AVPlayer){
self.player = player
}
func makeUIViewController(context: Context) -> some UIViewController {
return TrimVC(player: player)
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
}
}
Here's my View Controller
class TrimVC: UIViewController, TrimmerViewDelegate{
func didChangePositionBar(_ playerTime: CMTime) {
//
}
func positionBarStoppedMoving(_ playerTime: CMTime) {
//
}
let player: AVPlayer
init(player: AVPlayer){
self.player = player
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
var trimmerView: TrimmerView = TrimmerView()
override func viewDidLoad() {
trimmerView.delegate = self
view.addSubview(trimmerView)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
loadTrimmer()
}
func loadTrimmer() {
let frame = view.frame.inset(by: view.safeAreaInsets)
let viewWidth = frame.size.width
trimmerView.asset = player.currentItem?.asset
// THIS IS PRINTING MY CURRENT ASSET DIRECTORY.
print("Asset: \(player.currentItem?.asset)")
}
}
And This is How I'm calling it to my SwiftUI View
TrimView(player: player)
.background(Color.red)
.frame( height: UIScreen.screenHeight * 0.05)
But the trimmerView is not showing on my view but only the red square which I put to see if the view is available.
I am able to control the blur amount in iOS with help of fractionComplete then I am trying to do same work in macOS native app, I made a multi platform project which run for iOS and native macOS, the codes are in below, the version of iOS works just fine and looking to reach same effect of controlling the amount of blur in macOS, but unable to find a property works as fractionComplete in macOS version.
import SwiftUI
struct ContentView: View {
var body: some View {
ZStack {
Text("Hello, world!")
.font(Font.system(size: 50.0))
.padding()
.background(Color.yellow)
.fixedSize()
Text("Hello, world!")
.font(Font.system(size: 25.0))
.foregroundColor(Color.blue)
.padding(20)
.background(UnicornView())
.border(Color.blue)
}
}
}
#if os(iOS)
struct UnicornView: UIViewControllerRepresentable {
class UnicornControllerModel: UIViewController {
var animator = UIViewPropertyAnimator(duration: 1, curve: .linear)
var visualEffectView = UIVisualEffectView(effect: nil)
override func viewDidLoad() {
super.viewDidLoad()
animator.addAnimations {
self.visualEffectView.effect = UIBlurEffect(style: .systemUltraThinMaterial)
}
animator.fractionComplete = 0.2
view = visualEffectView
}
}
func makeUIViewController(context: UIViewControllerRepresentableContext<UnicornView>) -> UnicornControllerModel {
return UnicornControllerModel()
}
func updateUIViewController(_ uiViewController: UnicornControllerModel, context: UIViewControllerRepresentableContext<UnicornView>) {
}
}
#endif
#if os(macOS)
struct UnicornView: NSViewControllerRepresentable {
class UnicornControllerModel: NSViewController {
var animator = NSAnimation(duration: 1, animationCurve: .linear)
var visualEffectView = NSVisualEffectView()
init() {
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
visualEffectView.material = .popover
visualEffectView.blendingMode = .withinWindow
view = visualEffectView
}
override func loadView() {
view = NSView()
}
}
func makeNSViewController(context: NSViewControllerRepresentableContext<UnicornView>) -> UnicornControllerModel {
return UnicornControllerModel()
}
func updateNSViewController(_ nsViewController: UnicornControllerModel, context: NSViewControllerRepresentableContext<UnicornView>) {
}
}
#endif
I'm new in Swift and ARKit. For some reason the SCNNode node I'm trying to display is not showing up. I'm working with SwiftUI. I defined in the next code block the function addNode that should render the node.
import Foundation
import ARKit
import SwiftUI
// MARK: - ARViewIndicator
struct ARViewIndicator: UIViewControllerRepresentable {
typealias UIViewControllerType = ARView
func makeUIViewController(context: Context) -> ARView {
return ARView()
}
func updateUIViewController(_ uiViewController:
ARViewIndicator.UIViewControllerType, context:
UIViewControllerRepresentableContext<ARViewIndicator>) { }
}
class ARView: UIViewController, ARSCNViewDelegate {
var arView: ARSCNView {
return self.view as! ARSCNView
}
override func loadView() {
self.view = ARSCNView(frame: .zero)
}
override func viewDidLoad() {
super.viewDidLoad()
arView.delegate = self
arView.scene = SCNScene()
}
// MARK: - Functions for standard AR view handling
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let configuration = ARWorldTrackingConfiguration()
arView.debugOptions = [.showFeaturePoints,
.showWorldOrigin]
arView.session.run(configuration)
arView.delegate = self
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
arView.session.pause()
}
func addNode(){
let node = SCNNode()
node.geometry = SCNBox(width: 0.1,
height: 0.1,
length: 0.1,
chamferRadius: 0)
node.geometry?.firstMaterial?.diffuse.contents = UIColor.blue
node.position = SCNVector3(0,0,0.3)
arView.scene.rootNode.addChildNode(node)
arView.delegate = self
print(123)
}
// MARK: - ARSCNViewDelegate
func sessionWasInterrupted(_ session: ARSession) {}
func sessionInterruptionEnded(_ session: ARSession) {}
func session(_ session: ARSession, didFailWithError error: Error)
{}
func session(_ session: ARSession, cameraDidChangeTrackingState
camera: ARCamera) {}
}
... and that function is invoked when clicking the button "HOME"
import SwiftUI
import ARKit
// MARK: - NavigationIndicator
struct NavigationIndicator: UIViewControllerRepresentable {
typealias UIViewControllerType = ARView
func makeUIViewController(context: Context) -> ARView {
return ARView()
}
func updateUIViewController(_ uiViewController:
NavigationIndicator.UIViewControllerType, context:
UIViewControllerRepresentableContext<NavigationIndicator>) { }
}
struct ContentView: View {
#State var page = "Home"
var body: some View {
VStack {
ZStack {
NavigationIndicator()
VStack {
Spacer()
HStack {
Button("Home") {
let ar = ARView();
ar.addNode()
}.padding()
.background(RoundedRectangle(cornerRadius: 10)
.foregroundColor(Color.white).opacity(0.7))
Spacer()
}
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Do you know why it's not showing up ?
Thanks in advance !
Use this approach for SceneKitView:
import SwiftUI
import ARKit
struct SceneKitView: UIViewRepresentable {
let arView = ARSCNView(frame: .zero)
#Binding var pressed: Bool
#Binding var node: SCNNode
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
final class Coordinator: NSObject, ARSCNViewDelegate {
var control: SceneKitView
init(_ control: SceneKitView) {
self.control = control
}
func renderer(_ renderer: SCNSceneRenderer,
updateAtTime time: TimeInterval) {
if control.pressed {
self.control.node = self.addCube()
self.control.arView.scene.rootNode.addChildNode(control.node)
}
}
fileprivate func addCube() -> SCNNode {
control.node.geometry = SCNBox(width: 0.25,
height: 0.25,
length: 0.25,
chamferRadius: 0.01)
control.node.geometry?.firstMaterial?.diffuse.contents = UIColor.blue
control.node.geometry?.firstMaterial?.lightingModel = .phong
control.node.position = SCNVector3(0, 0,-2)
return control.node
}
}
func makeUIView(context: Context) -> ARSCNView {
arView.scene = SCNScene()
arView.delegate = context.coordinator
arView.autoenablesDefaultLighting = true
arView.debugOptions = .showFeaturePoints
// arView.allowsCameraControl = true
let config = ARWorldTrackingConfiguration()
arView.session.run(config)
return arView
}
func updateUIView(_ uiView: ARSCNView,
context: Context) { }
}
Then use this code for ContentView.
struct ContentView: View {
#State var pressed: Bool = false
#State var node = SCNNode()
var body: some View {
ZStack {
SceneKitView(pressed: $pressed, node: $node)
VStack {
Spacer()
HStack {
Button("Blue Cube") {
pressed.toggle()
}.padding()
.foregroundColor(.red)
Spacer()
}
}
}
}
}
P.S.
However, a strange issue occurs with ARSCNView in Simulator – after pressing a button a SCNBox appears only after tapping a screen with .allowsCameraControl = true.
Does somebody have all ready implemented a search bar using Apple component like UISearchBar with swiftui on tvos ?
I tried this UISearchBar(frame: .zero) but I got this error init(frame:)' is unavailable in tvOS
I only found solutions for ios.
The scheme of initial setup should be like below. Of course, the logic of searching/filtering/showing results is app specific.
import SwiftUI
import TVUIKit
struct SearchView: UIViewControllerRepresentable {
func makeUIViewController(context: UIViewControllerRepresentableContext<SearchView>) -> UINavigationController {
let controller = UISearchController(searchResultsController: context.coordinator)
controller.searchResultsUpdater = context.coordinator
return UINavigationController(rootViewController: UISearchContainerViewController(searchController: controller))
}
func updateUIViewController(_ uiViewController: UINavigationController, context: UIViewControllerRepresentableContext<SearchView>) {
}
func makeCoordinator() -> SearchView.Coordinator {
Coordinator()
}
typealias UIViewControllerType = UINavigationController
class Coordinator: UIViewController, UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
// do here what's needed
}
}
}
struct ContentView: View {
#State private var text: String = ""
var body: some View {
VStack {
SearchView()
Spacer()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
So I've wrapped WKWebView in an UIViewRepresentable and built a coordinator in order to access its navigation delegate's functions. In the webView(_:didFinish:) function I am trying to update the view's didFinishLoading variable. If I print right after assigning, it prints true - the expected behavior. But, in the parent view, when I call the getHTML function, it prints false - even if I wait until the WKWebView is fully loaded.
Here is the code:
import SwiftUI
import WebKit
struct WebView: UIViewRepresentable {
#Binding var link: String
init(link: Binding<String>) {
self._link = link
}
private var didFinishLoading: Bool = false
let webView = WKWebView()
func makeUIView(context: UIViewRepresentableContext<WebView>) -> WKWebView {
self.webView.load(URLRequest(url: URL(string: self.link)!))
self.webView.navigationDelegate = context.coordinator
return self.webView
}
func updateUIView(_ uiView: WKWebView, context: UIViewRepresentableContext<WebView>) {
return
}
class Coordinator: NSObject, WKNavigationDelegate {
private var webView: WebView
init(_ webView: WebView) {
self.webView = webView
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("WebView: navigation finished")
self.webView.didFinishLoading = true
}
}
func makeCoordinator() -> WebView.Coordinator {
Coordinator(self)
}
func getHTML(completionHandler: #escaping (Any?) -> ()) {
print(self.didFinishLoading)
if (self.didFinishLoading) {
self.webView.evaluateJavaScript(
"""
document.documentElement.outerHTML.toString()
"""
) { html, error in
if error != nil {
print("WebView error: \(error!)")
completionHandler(nil)
} else {
completionHandler(html)
}
}
}
}
}
struct WebView_Previews: PreviewProvider {
#State static var link = "https://apple.com"
static var previews: some View {
WebView(link: $link)
}
}
Here is your code, a bit modified for demo, with used view model instance of ObservableObject holding your loading state.
import SwiftUI
import WebKit
import Combine
class WebViewModel: ObservableObject {
#Published var link: String
#Published var didFinishLoading: Bool = false
init (link: String) {
self.link = link
}
}
struct WebView: UIViewRepresentable {
#ObservedObject var viewModel: WebViewModel
let webView = WKWebView()
func makeUIView(context: UIViewRepresentableContext<WebView>) -> WKWebView {
self.webView.navigationDelegate = context.coordinator
if let url = URL(string: viewModel.link) {
self.webView.load(URLRequest(url: url))
}
return self.webView
}
func updateUIView(_ uiView: WKWebView, context: UIViewRepresentableContext<WebView>) {
return
}
class Coordinator: NSObject, WKNavigationDelegate {
private var viewModel: WebViewModel
init(_ viewModel: WebViewModel) {
self.viewModel = viewModel
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("WebView: navigation finished")
self.viewModel.didFinishLoading = true
}
}
func makeCoordinator() -> WebView.Coordinator {
Coordinator(viewModel)
}
}
struct WebViewContentView: View {
#ObservedObject var model = WebViewModel(link: "https://apple.com")
var body: some View {
VStack {
TextField("", text: $model.link)
WebView(viewModel: model)
if model.didFinishLoading {
Text("Finished loading")
.foregroundColor(Color.red)
}
}
}
}
struct WebView_Previews: PreviewProvider {
static var previews: some View {
WebViewContentView()
}
}