4

I've gone through every post and article but have yet to solve my problem and I'm not sure why. I have a table view which if the piece of content is an image, it will show an image in the TableViewCell, otherwise it will show a video in it. For the video, I have the link printed so it's there and the link works, but for some reason in the TableViewCell the video doesn't play and it's just black.

Here is the code for the TableViewCell:

import UIKit
import AVFoundation

class ViewImageCell: UITableViewCell {

var avQueuePlayer   : AVQueuePlayer?
var avPlayerLayer   : AVPlayerLayer?



let postContentView: UIView = {
    let view = UIView()

    return view
}()

   let contentImageView: UIImageView = {
       let imageView = UIImageView()
       imageView.translatesAutoresizingMaskIntoConstraints = false
       imageView.layer.masksToBounds = true
       imageView.autoresizesSubviews = true
       imageView.contentMode = .scaleAspectFit
       imageView.image = UIImage(named: "ProfileIcon")

      return imageView
   }()


override func awakeFromNib() {
    super.awakeFromNib()


    // Initialization code


}

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
}


override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: .default, reuseIdentifier: reuseIdentifier)

    addSubview(postContentView)
    addSubview(contentImageView)
    postContentView.anchor(top: self.topAnchor, left: self.leftAnchor, bottom: self.bottomAnchor, right: self.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
    contentImageView.anchor(top: self.topAnchor, left: self.leftAnchor, bottom: self.bottomAnchor, right: self.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
}


   required init?(coder aDecoder: NSCoder) {
       fatalError("init(coder:) has not been implemented")
   }

func addPlayer(for url: URL) {
    self.avQueuePlayer = AVQueuePlayer(url: url)
    self.avPlayerLayer = AVPlayerLayer(player: self.avQueuePlayer!)
    self.avPlayerLayer?.frame = self.postContentView.bounds
    self.avPlayerLayer?.fillMode = .both
    self.postContentView.layer.addSublayer(self.avPlayerLayer!)
    self.avQueuePlayer?.play()
}

   func bindData(content: NSDictionary) {

    if content[kPICTURE] != nil {

        let data = content[kPICTURE] as! String
        let picData = NSData(base64Encoded: data, options: [])

        if let image = UIImage(data: picData! as Data) {
            contentImageView.image = image
        } else {
            print("There was an error loading the pic")
        }

    } else {

    }

    if content[kVIDEO] != nil {
        contentImageView.isHidden = true
        let videoData = content[kVIDEO] as! String
           let url = NSURL(fileURLWithPath: videoData)
        addPlayer(for: url as URL)
           print("Here is a video")

    } else {
        //
    }

}
}

Here is a piece of the code for the TableView:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if indexPath.section == 0 {
        let cell = tableView.dequeueReusableCell(withIdentifier: imageCellID, for: indexPath) as! ViewImageCell

        if singleContent != nil {

            cell.bindData(content: singleContent)

        } else {
            print("Can't find singleContent")
        }

        return cell
    }




    return UITableViewCell()
}

Let me know if you have any questions and need more clarification. All help is greatly appreciated.

EDIT: Here is an example of the type of video path I'm using. I'm taking this from my Firebase Database, not a local file in my project.

file:///private/var/mobile/Containers/Data/PluginKitPlugin/49C0EAA4-9825-4D06-8CFB-6136FF5BCC3C/tmp/trim.AA010490-81F0-43C8-AE8A-1029D5AF55E1.MOV

I also get the error code below. I looked and think it means that the file doesn't exist, but I can still view that file else where in a different view it plays the video.

NSURLConnection finished with error - code -1100

Here is where the video path is stored in the database, not using Firebase Storage at all. enter image description here

Jaqueline
  • 465
  • 2
  • 8
  • 25

2 Answers2

1

If you want to play video URL in webview use below code: (manage code as per your requirement)

func bindData(content: NSDictionary)
{

    if content[kPICTURE] != nil {

        let data = content[kPICTURE] as! String
        let picData = NSData(base64Encoded: data, options: [])

        if let image = UIImage(data: picData! as Data) {
            contentImageView.image = image
        } else {
            print("There was an error loading the pic")
        }

    } else {

    }

    if content[kVIDEO] != nil {
        contentImageView.isHidden = true
        let videoData = content[kVIDEO] as! String

        //let url = NSURL(fileURLWithPath: videoData)


        let storageRef = Storage.storage().reference(forURL: <YourFilePathURL>)
storageRef.getData(maxSize: INT64_MAX) { (data, error) in
    if let error = error {
        print("Error downloading image data: \(error)")
        return
    }
    storageRef.getMetadata(completion: { (metadata, metadataErr) in

        if let error = metadataErr {
            print("Error downloading metadata: \(error)")
            return
        }
        if (metadata?.contentType == "image/gif") {
            print("It is Gif")
        } else {
            let downloadUrl = metadata?.downloadURL()
            if downloadUrl != nil{
 print(downloadUrl)
       //You will get your Video Url Here
        self.PlayVideoInWEbView(downloadUrl)
        print("Here is a video")

    }

        }
    })
}
    } else {
        //
    }

}

func PlayVideoInWEbView(_ videoURL : String)
{
    let myWebView:UIWebView = UIWebView(frame: CGRect(x: 20, y: 20, width: self.viewCell.frame.width, height: 200))



    myWebView.delegate = self

    let myURL = URL(string: videoURL)
    let myURLRequest:URLRequest = URLRequest(url: myURL!)
    myWebView.loadRequest(myURLRequest)

    self.viewCell.addSubview(myWebView)

}
  • I've tried your method and it works perfectly when having a link; however, it doesn't work when I have a video with a path. I've tried to alter it with the NSURL(fileURLWithPath) but it still doesn't show. Do you know how I can tweak it to get it working for my purposes? – Jaqueline Mar 13 '20 at 03:43
  • @Jaqueline if your video is store in local path then you need to make url with help of bundle code. if you have local video path then check my updated answer. – PALAK Mobile Team Leader Mar 13 '20 at 06:49
  • I just updated my question with an example of the video path that I'm using which loads from my Firebase Database, not a Bundle Resource. I really appreciate your help! – Jaqueline Mar 14 '20 at 02:12
  • the path you update in your question is for firebase file. So if you directly call this path to NSURLConnection so you will get error of 1100. My suggestion you to first download url from this path and then pass that url in URL connection to play the video. when you get proper URL then you can check it by paste that URL in any browser and it will play properly. – PALAK Mobile Team Leader Mar 14 '20 at 06:13
  • Would you be able to explain that process for me? I haven’t gone about it this way before – Jaqueline Mar 14 '20 at 06:29
  • https://firebase.google.com/docs/storage/ios/download-files from this link you get better idea. you can also check with your firebase code. – PALAK Mobile Team Leader Mar 14 '20 at 06:41
  • how does it work if I’m not using firebase storage? The video path is stored as a child in my firebase. – Jaqueline Mar 14 '20 at 16:29
  • @Jaqueline, please check my updated answer it may help you. – PALAK Mobile Team Leader Mar 14 '20 at 20:32
  • Like I said, I’m not using Firebase Storage at all. The video path is stored as a child in the Database. Please check my updated question for clarification. Thanks – Jaqueline Mar 14 '20 at 20:58
1

@Jaqueline Try like below If you have or stored a recorded video into the local document directory.

func bindData(content: NSDictionary) {

    if content[kPICTURE] != nil {

        let data = content[kPICTURE] as! String
        let picData = NSData(base64Encoded: data, options: [])

        if let image = UIImage(data: picData! as Data) {
            contentImageView.image = image
        } else {
            print("There was an error loading the pic")
        }

    } else {
    }

    if content[kVIDEO] != nil {
        contentImageView.isHidden = true
        //let videoData = content[kVIDEO] as! String

        //let url = NSURL(fileURLWithPath: videoData)

        let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
        let url = NSURL(fileURLWithPath: path)
        let filePath = url.appendingPathComponent("/video.mp4")!.path

        let videoData = URL(fileURLWithPath: filePath)

        //addPlayer(for: url as URL) //remove this line and add below line

        self.PlayVideoInWEbView(videoData)
        print("Here is a video")

    } else {
        //
    }
}

func PlayVideoInWEbView(_ videoURL : String) {
    let myWebView:WKWebView = WKWebView(frame: CGRect(x: 20, y: 20, width: self.viewCell.frame.width, height: 200))

    //myWebView.delegate = self

    myWebView.uiDelegate = self
    myWebView.navigationDelegate = self

    let myURL = URL(string: videoURL)
    let myURLRequest:URLRequest = URLRequest(url: myURL!)
    //myWebView.loadRequest(myURLRequest)

    myWebView.load(myURLRequest)

    self.viewCell.addSubview(myWebView)
}

//MARK: - WKNavigationDelegate
extension YourViewControllerClass: WKNavigationDelegate {

    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        //Here hide your loading indicator
    }

    func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {

        DDLogDebug("webViewWebContentProcessDidTerminate ==> \(webView)")
    }

    func webView(_ webView: UIWebView, didFailLoadWithError error: Error) {
        //Here hide your loading indicator
    }
}

Hope it will help your required output!!!.

Ram
  • 764
  • 1
  • 7
  • 20
  • I just updated my question with an example of the video path that I'm using which loads from my Firebase Database, not a Bundle Resource. I really appreciate your help! – Jaqueline Mar 14 '20 at 02:13
  • @Jaqueline Try with `WKWebView instead of using UIWebView`. Load this video file `file:///private/var/mobile/Containers/Data/PluginKitPlugin/49C0EAA4-9825-4D06-8CFB-6136FF5BCC3C/tmp/trim.AA010490-81F0-43C8-AE8A-1029D5AF55E1.MOV` to `WKWebView` - Hope it will get your desired output. – Ram Mar 16 '20 at 06:36
  • @Jaqueline I have updated my answer kindly check it. – Ram Mar 16 '20 at 06:42
  • Thank you for your response. When I tried it, the console got swarmed with [Process] kill() returned unexpected error 1 which I don't understand what that means except for it has to do with the WKWebView. The video also doesn't play it's just a white view. I tried adding an AVPlayer to my cell, which works perfectly but there's one bug with it. Do you think you could check out my post about it? https://stackoverflow.com/questions/60699431/avplayer-doesnt-play-video-until-a-video-from-uiimagepickercontroller-is-played Thanks! – Jaqueline Mar 16 '20 at 20:13
  • @Jaqueline Okay sure let me check it. – Ram Mar 17 '20 at 06:41