集合视图内容未显示在视图中

Posted

技术标签:

【中文标题】集合视图内容未显示在视图中【英文标题】:Collection view content not showing in view 【发布时间】:2020-01-17 10:34:40 【问题描述】:

我不知道为什么会发生这种情况,我有一个不同的 Xcode 项目,它具有完全相同的集合视图,只是为了测试并制作它,我已经完成了它,它在那个项目中运行良好。然后我将所有代码和项目移到我的主 Xcode 项目中,当我播放应用程序时,集合视图没有显示在我的视图控制器中。

如何调试集合视图?这两个:playerCollect?.cellForItem(at: path)playerCollect.indexPathForItem(at: p) 如果这是个问题,都返回 nil?我不知道。一旦我将它转移到我的主要项目中,我可能还没有将所有东西重新连接在一起,但是你又是如何找到它的呢?这是包含 UICollectionView 的 viewController 的完整代码:

import UIKit
import AVKit
import Firebase
import MMPlayerView


class HomeViewController: 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")


@IBAction func profileButtonTap(_ sender: Any) 
    let uid = (Auth.auth().currentUser?.uid)!
    let Splash = SpalshScreenViewController()
    Splash.GetProfilePicture(uid: uid)
    Splash.GetUsername(uid: uid)
    Splash.GetName(uid: uid)
    Splash.GetClipsNumber(uid: uid)
    Splash.GetFollowersNumber(uid: uid)
    Splash.GetFollowingsNumber(uid: uid)
    performSegue(withIdentifier: "showProfile", sender: nil)



extension HomeViewController: MMPlayerFromProtocol 
     func backReplaceSuperView(original: UIView?) -> UIView? 
        guard let path = self.findCurrentPath(),
            let cell = self.findCurrentCell(path: path) as? PlayerCell else 
            return original
    
    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 HomeViewController: 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.contentOffset.x + playerCollect.frame.width/2, y: playerCollect.frame.height/2)
print(playerCollect.indexPathForItem(at: p))
    return playerCollect.indexPathForItem(at: p)


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



extension HomeViewController: 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()


【问题讨论】:

检查您的UICollectionView 代表和数据源?你有没有从情节提要中连接它? @HardikS 我该怎么做才能从 swift 文件中做到这一点? 【参考方案1】:

您是否在此视图控制器中提供了集合视图的委托和数据源?

self.playerCollect.delegate = self
self.playerCollect.dataSource = self

并添加:

self.playerCollect.reloadData()

【讨论】:

我该怎么做才能从 swift 文件中做到这一点? 在 ViewDidLoad : playerCollect.dataSource = self 和 playerCollect.delegate = self 和 playerCollect.reloadData() 你的类应该是: class HomeViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource 这很奇怪,我之前的项目不需要设置两个就可以了,我猜这只是一个简单的连接? 我不应该在课堂上这样做,因为我有扩展来这样做【参考方案2】:

如下更新您的代码。

class HomeViewController: UIViewController 
    override func viewDidLoad() 
                super.viewDidLoad()

                // Do any additional setup after loading the view.

               self.playerCollect.delegate = self
               self.playerCollect.dataSource = self
    



extension HomeViewController: UICollectionViewDataSource, 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()
    

【讨论】:

以上是关于集合视图内容未显示在视图中的主要内容,如果未能解决你的问题,请参考以下文章

标题部分未以编程方式显示在集合视图中

图像未显示在集合视图单元格中

集合视图未加载图像

Swift 中的 Xcode:导航栏未显示在 UI 集合视图(模拟器)中

根据标题内的集合视图动态内容显示集合视图的标题大小不起作用

集合视图单元格未出现