Почему сборный вид занимает sh, когда я изменяю направление прокрутки с вертикального на горизонтальное? - PullRequest
0 голосов
/ 16 января 2020

У меня есть представление коллекции, которое показывает группу видео любого объекта данных, который я передаю. Когда вы нажимаете на одно из видео в представлении содержимого, открывается новый вид (DetailViewController), и видео отображается в более подробном представлении. В этом DetailViewController есть кнопка «Назад», которая закрывает представление и возвращает вас на главную страницу с представлением коллекции - то есть, когда происходит cra sh, когда я go из этого DetailViewController возвращаю контроллер основного представления.

Все отлично работает, когда «направление прокрутки» в представлении коллекции установлено в вертикальное положение, но когда я устанавливаю его в горизонтальное положение (что я и хочу), происходит сбой, как описано выше.

cra sh:

Unexpectedly found nil while unwrapping an Optional value

, а источник:

private func findCurrentCell(path: IndexPath) -> UICollectionViewCell {
    return playerCollect.cellForItem(at: path)!
}

Я предполагаю, что path или IndexPath нет обновляется, когда пользователь прокручивает, чтобы индекс не обновлялся?

Есть идеи? При необходимости я могу предоставить видео или дополнительный код.

РЕДАКТИРОВАТЬ (дополнительный код):

import UIKit
import AVFoundation
import MMPlayerView

class ViewController: UIViewController {
    var offsetObservation: NSKeyValueObservation?
    lazy var mmPlayerLayer: MMPlayerLayer = {
    let l = MMPlayerLayer()        
    l.cacheType = .memory(count: 5)
    l.coverFitType = .fitToPlayerView
    l.videoGravity = AVLayerVideoGravity.resizeAspect
    l.replace(cover: CoverA.instantiateFromNib())
    l.repeatWhenEnd = true
    return l
}()

@IBOutlet weak var playerCollect: UICollectionView!
override func viewDidLoad() {
    super.viewDidLoad()
    // remove previous download fails file
    MMPlayerDownloader.cleanTmpFile()
    self.navigationController?.mmPlayerTransition.push.pass(setting: { (_) in

    })
    offsetObservation = playerCollect.observe(\.contentOffset, options: [.new]) { [weak self] (_, value) in
        guard let self = self, self.presentedViewController == nil else {return}
        NSObject.cancelPreviousPerformRequests(withTarget: self)
        self.perform(#selector(self.startLoading), with: nil, afterDelay: 0.2)
    }
    playerCollect.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 200, right:0)
    DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
        self?.updateByContentOffset()
        self?.startLoading()
    }

    mmPlayerLayer.getStatusBlock { [weak self] (status) in
        switch status {
        case .failed(let err):
            let alert = UIAlertController(title: "err", message: err.description, preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
            self?.present(alert, animated: true, completion: nil)
        case .ready:
            print("Ready to Play")
        case .playing:
            print("Playing")
        case .pause:
            print("Pause")
        case .end:
            print("End")
        default: break
        }
    }
    mmPlayerLayer.getOrientationChange { (status) in
        print("Player OrientationChange \(status)")
    }
}

deinit {
    offsetObservation?.invalidate()
    offsetObservation = nil
    print("ViewController deinit")
}
}


func backReplaceSuperView(original: UIView?) -> UIView? {
    guard let path = self.findCurrentPath() else {
        return original
    }

    let cell = self.findCurrentCell(path: path) as! PlayerCell
    return cell.imgView
}

// add layer to temp view and pass to another controller
var passPlayer: MMPlayerLayer {
    return self.mmPlayerLayer
}
func transitionWillStart() {
}
// show cell.image
func transitionCompleted() {
    self.updateByContentOffset()
    self.startLoading()
}
}

extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let m = min(UIScreen.main.bounds.size.width, UIScreen.main.bounds.size.height)
    return CGSize(width: m, height: m*0.75)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
   DispatchQueue.main.async { [unowned self] in
    if self.presentedViewController != nil || self.mmPlayerLayer.isShrink == true {
            //self.playerCollect.scrollToItem(at: indexPath, at: .centeredVertically, animated: true)
            //self.updateDetail(at: indexPath)
        } else {
            self.presentDetail(at: indexPath)
        }
    }
}

fileprivate func updateByContentOffset() {
    if mmPlayerLayer.isShrink {
        return
    }

    if let path = findCurrentPath(),
        self.presentedViewController == nil {
        self.updateCell(at: path)
        //Demo SubTitle
        if path.row == 0, self.mmPlayerLayer.subtitleSetting.subtitleType == nil {
            let subtitleStr = Bundle.main.path(forResource: "srtDemo", ofType: "srt")!
            if let str = try? String.init(contentsOfFile: subtitleStr) {
                self.mmPlayerLayer.subtitleSetting.subtitleType = .srt(info: str)
                self.mmPlayerLayer.subtitleSetting.defaultTextColor = .red
                self.mmPlayerLayer.subtitleSetting.defaultFont = UIFont.boldSystemFont(ofSize: 20)
            }
        }
    }
}

fileprivate func presentDetail(at indexPath: IndexPath) {
    self.updateCell(at: indexPath)
    mmPlayerLayer.resume()

    if let vc = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "DetailViewController") as? DetailViewController {
        vc.data = DemoSource.shared.demoData[indexPath.row]
        self.present(vc, animated: true, completion: nil)
    }
}

fileprivate func updateCell(at indexPath: IndexPath) {
    if let cell = playerCollect.cellForItem(at: indexPath) as? PlayerCell, let playURL = cell.data?.play_Url {
        // this thumb use when transition start and your video dosent start
        mmPlayerLayer.thumbImageView.image = cell.imgView.image
        // set video where to play
        mmPlayerLayer.playView = cell.imgView
        mmPlayerLayer.set(url: playURL)
    }
}

@objc fileprivate func startLoading() {
    self.updateByContentOffset()
    if self.presentedViewController != nil {
        return
    }
    // start loading video
    mmPlayerLayer.resume()
}

private func findCurrentPath() -> IndexPath? {
    let p = CGPoint(x: playerCollect.frame.width/2, y: playerCollect.contentOffset.y + playerCollect.frame.width/2)
    return playerCollect.indexPathForItem(at: p)
}

private func findCurrentCell(path: IndexPath) -> UICollectionViewCell {
    return playerCollect.cellForItem(at: path)!
}
}

extension ViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return DemoSource.shared.demoData.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PlayerCell", for: indexPath) as? PlayerCell {
        cell.data = DemoSource.shared.demoData[indexPath.row]
        return cell
    }
    return UICollectionViewCell()
}
}

1 Ответ

1 голос
/ 16 января 2020

Неправильно использовать принудительный необязательный оператор !, поскольку он часто приводит к сообщению об ошибке, которое вы описали. Ваш findCurrentPath расчет не был обновлен для горизонтального перемещения. Во-первых, измените ваш findCurrentPath метод на (что, я полагаю, вы пытаетесь достичь):

private func findCurrentPath() -> IndexPath? {
    let p = CGPoint(x: playerCollect.contentOffset.x + playerCollect.frame.width/2, 
                    y: playerCollect.frame.height/2)
    return playerCollect.indexPathForItem(at: p)
}

Чтобы предотвратить сбой, даже если он не работает именно так, как вы хотите, я убрал только два другие методы, потому что слишком много принудительных опциональных операторов для их всех; измените ваш findCurrentCell метод на следующий:

private func findCurrentCell(path: IndexPath) -> UICollectionViewCell? {
   return playerCollect.cellForItem(at: path)
}

и, наконец, ваш backReplaceSuperView метод на:

 func backReplaceSuperView(original: UIView?) -> UIView? {
    guard let path = self.findCurrentPath(),
        let cell = self.findCurrentCell(path: path) as? PlayerCell else {
        return original
    }
    return cell.imgView
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...