Search code examples
iosswiftuiviewwkwebviewxib

Swift - How to manipulate outlet in nib while "viewWillDisappear" on ViewController?


DetailCollectionViewCell includes a WKWebView that loads specific video and text embedded from the server. My goal is when the user clicks the back button, the video should be stopped. I've tried reloading or setting WebView's URL to nil, but I get Fatal Error and nil value for Web View every time I try to effect detailWebView.

.
├── _PageViewController.swift
│   └── viewWillDisappear()
├── _DetailCollectionViewCell.swift (File Owner of the nib)
└── └── WKWebView: detailWebView

DetailCollectionViewCell.swift (Where I populate data for WebView.)

@objc protocol DetailCollectionViewCellDelegate  {
        func reload()
        @objc func scrollAuthorAllColumns()
    }

class DetailCollectionViewCell: UICollectionViewCell {
    @IBOutlet weak var detailWeb: WKWebView!
    var delegate: DetailCollectionViewCell?

    override func awakeFromNib() {
        super.awakeFromNib()

        detailWeb.navigationDelegate = self
        detailWeb.uiDelegate = self;
        detailWeb.autoresizingMask = UIView.AutoresizingMask(rawValue: UIView.AutoresizingMask.flexibleWidth.rawValue | UIView.AutoresizingMask.flexibleHeight.rawValue)
    }

    var itemAuthor: Column? {
        didSet {
            if let column = itemAuthor {
                if(PageViewController.itemId != column.itemId) {
                    let webViewHeight = 50 as CGFloat
                    self.webViewHeight.constant = webViewHeight
                    self.wKWebViewHeight.constant = webViewHeight
                    self.detailWeb.frame.size.height = webViewHeight
                    DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                        if(PageViewController.webViewHg <= Int(webViewHeight)) {
                            HUD.show(HUDContentType.progress)
                        }
                    }
                    
                    self.detailWeb.isHidden = true
                    self.delegate?.reload()
                    
                    let HTMLString = "my HTML string"
                    
                    detailWeb.loadHTMLString(String(HTMLString), baseURL: URL.init(fileURLWithPath: Bundle.main.bundlePath))
                }
            }
        }
    }
}

PageViewController.swift

    override func viewWillDisappear(_ animated: Bool) {
        DetailCollectionViewCell.detailWeb.reload() "<--------- Crashes here. detailWebView = nil"
        "Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value"
    }

    extension PageViewController: DetailCollectionViewCellDelegate {
    func reload() {
        DispatchQueue.main.async{
            self.collectionView.collectionViewLayout.invalidateLayout()
        }
    }
    
    func scrollAuthorAllColumns() {
        collectionView.scrollToItem(at: IndexPath.init(row: 0, section: 1), at: .top, animated: true)
    }

Solution

  • I've used this method to achieve my goal.

    Basically what it does is, disables in-line playback and only allows tvPlayer to play on full-screen thus when the user closes full-screen, the video stops.