При создании нового объекта в Core Data WKWebView перестает отвечать (SwiftUI)

#core-data #swiftui #wkwebview

#core-data #swiftui #wkwebview

Вопрос:

У меня есть WKWebView, который воспроизводит видео на YouTube. Я собрал функциональность воспроизведения / паузы и многое другое. В настоящее время я пытаюсь реализовать CoreData и пытаюсь сохранить информацию о видео YT, которые воспроизводятся в данный момент, например, название видео и идентификатор видео и многое другое.

Я могу сохранить данные, и я также могу видеть свои сохраненные данные, и я могу их удалить. Однако я заметил, что при попытке сохранить видео моя кнопка воспроизведения / паузы больше не работает. Я обнаружил проблему в своих действиях WKWebView, которые больше не работают после сохранения в CoreData, но они работают, пока я не попытаюсь сохранить.

Вызываются функции playVideo и pauseVideo, но кажется, что WKWebView больше не отвечает по какой-то странной причине

Итак, моя проблема в том, почему мой WKWebView больше не отвечает?

Вот как я реализовал свой WKWebView

 var webview: WKWebView?
    var videoID: String
    let hardcodedPlaylist: [String] = ["EQIh607kd0Y", "A5kGigZHed4", "MLJyFzdQfK8", "Trfxm0TJwuQ", "nVVr7gJNny8", "XqZsoesa55w"]
    
    func createEmbededHtml(videoID: String, playlist: String) -> String {
            return """
                <!DOCTYPE html>
                   <html>
                   <style>
                       * { margin: 0; padding: 0; }
                       html, body { width: 100%; height: 100%; }
                   </style>
                    <body>
                      <!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
                      <div id="player" ></div>



                      <script>
                        // 2. This code loads the IFrame Player API code asynchronously.
                        var tag = document.createElement('script');

                        tag.src = "https://www.youtube.com/iframe_api";
                        var firstScriptTag = document.getElementsByTagName('script')[0];
                        firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

                        // 3. This function creates an <iframe> (and YouTube player)
                        //    after the API code downloads.
                        var player;
                        function onYouTubeIframeAPIReady() {
                          player = new YT.Player('player', {
                            height: '100%',
                            width: '100%',
                            videoId: '(videoID)',
                            playerVars: {
                               controls: 0,
                               rel: 0,
                               modestbranding: 1,
                               playsinline: 1,
                               enablejsapi: 1,
                               playlist: '(playlist)'
                           },
                            events: {
                              'onReady': onPlayerReady
                            }
                          });
                        }

                        // 4. The API will call this function when the video player is ready.
                        function onPlayerReady(event) {
                           player.playVideoAt(1);
                        }

                      </script>
                    </body>
                   </html>
                """
    }
    
    init(web: WKWebView?, videoID: String) {
        let configuration = WKWebViewConfiguration()
        configuration.allowsInlineMediaPlayback = true
        configuration.mediaTypesRequiringUserActionForPlayback = []
        self.webview = WKWebView(frame: .zero, configuration: configuration)
        self.videoID = videoID
    }
    
    func makeUIView(context: Context) -> WKWebView {
        let embededHtmlString = createEmbededHtml(videoID: videoID, playlist: hardcodedPlaylist.joined(separator: ", "))
        self.webview?.navigationDelegate = context.coordinator
        webview?.isUserInteractionEnabled = false
        webview?.isOpaque = false
        webview?.loadHTMLString(embededHtmlString, baseURL: nil)
        return webview!
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {
    }
    
    class Coordinator: NSObject, WKNavigationDelegate {
        private var webViewModel: WebViewModel
        
        init(_ webViewModel: WebViewModel) {
            self.webViewModel = webViewModel
        }
        
        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            print("webview has loaded")
            self.webViewModel.didFinishLoading = true
        }
    
    }
    
    func makeCoordinator() -> Webview.Coordinator {
        Coordinator(webViewModel)
    }
    
    func playVideo() {
        webview?.evaluateJavaScript("player.playVideo()")
        print("playing...")
    }
    
    func pauseVideo() {
        webview?.evaluateJavaScript("player.pauseVideo()")
        print("pauseing...")
    }
 

Этот код находится в классе с именем Webview, чтобы показать как можно меньше кода, я не буду показывать, как я вызываю свой Webview, я не думаю, что это будет служить цели.

Вот фрагмент с кодом моей кнопки, которая используется для сохранения видео, я также включил код для saveVideo и saveContext

 Button(action: {
                print("saving button pressed")
                
                let currentIndex = webViewModel.playlistIndex - 1
                saveVideo(videoID: videoIDFetcherInfo.videoIDs[webViewModel.playlistIndex] ,title: videoIDFetcherInfo.videoTitles[currentIndex], thumbnailUrlString: videoIDFetcherInfo.VideoThumbnailsUrl[currentIndex])
}, label: {
                Image(videoSaved.isVideoSaved ? "bookmark-border-filled" : "bookmark-border")
                    .sizeShadowModifier(size: 44, shadowRadius: 12, shadowX: 2, shadowY: 6)
            })

 func saveVideo(videoID: String, title: String, thumbnailUrlString urlString: String) {
        let newVideo = Video(context: managedObjectContext)
        
        newVideo.thumbnailUrlString = urlString
        newVideo.title = title
        newVideo.videoID = videoID
        newVideo.createdAt = Date()
        
        
        print("Saving Video")
        
        saveContext()
    }
    
    func saveContext() {
        do {
            try managedObjectContext.save()
        } catch {
            //TODO: add alert instead
            print("There was an error saving")
        }
    } 
 

После вызова saveVideo моя кнопка для воспроизведения / приостановки больше не работает, но видео сохраняется, и я вижу, что также соответствующая функция вызывается внутри Webview. Также я разрабатываю для iOS 14 и использую Xcode 12.3 и использую только SwiftUI