繁体   English   中英

您如何正确地将数据传递到 NSObject 类以从 Firebase 获取集合视图

[英]How do you properly pass data to a NSObject class for a collection view from Firebase

您如何正确地将数据发送到集合视图的自定义数据 NSObject 类? 我的变量总是返回为零。

我在它自己的视图控制器中有一个闪屏。 当所有我想要加载的数据加载完成后,从火力点,我通过到应用程序的主屏幕performSegue(withIdentifier:) ,下面是从问题的代码的代码SplashScreenViewController

   func getDatabaseReference(){
    let d = DispatchGroup()
    d.enter()
    let encodedURL = (postIDRefDic["post1"]! + "/postURL")
    ref.child(encodedURL).observe(.value, with: { (snapshot) in
        let newUrl = snapshot.value as! String
        DemoSource.shared.url = newUrl
        d.leave()
    })
    d.notify(queue: .main){
        self.performSegue(withIdentifier: "showHome", sender: nil)
    }
}

在上面的代码中,您可以看到我正在使用我的下一个视图控制器HomeViewController ,在 HomeViewController 类中我有一个集合视图,它由一个名为DemoSource (也显示在上面)的自定义类(NSObject 类)帮助我' 用于分配我刚刚在该类中的变量中获得的新数据。 这个DemoSource类是一个NSObject类型的自定义数据类:

import UIKit
import Firebase

struct DataObj {
    var image: UIImage?
    var play_Url: URL?
    var title = ""
    var content = ""
}

class DemoSource: NSObject {
static let shared = DemoSource()
var demoData = [DataObj]()
var url = ""

override init() {

    demoData += [
                  DataObj(image: #imageLiteral(resourceName: "ss-1") , play_Url: URL(string: url), title: "title ", content: "Description")
    ]
}

}

我将这个类与我的 HomeViewController 和集合视图一起使用:

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 {
           }
        }
    }
}

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)
    return playerCollect.indexPathForItem(at: p)
}

private func findCurrentCell(path: IndexPath) -> UICollectionViewCell? {
   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()
}
}

我第一次实例化Demosource类是:

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()
}
}

当我运行我的应用程序时,它显然崩溃了,数据类中的 url 为零,即使我在我的 splashscreenviewcontroller 中使用 url 设置它? 当我使用断点进行一些调试时,这个DemoSource类在变量被填充之前就被实例化了。

所以我的问题是,在所有这些解释之后......为什么DemoSource类中的 url 变量仍然为零,为什么在使用此类的视图仅在从其获取数据之后才调用该类之前执行该类火力基地?

您已将DemoSource实现为单例,这意味着它在您第一次引用DemoSource.shared时被实例化。 这是在getDatabaseReference 当它被实例化时, url有它的初始值 (""),所以它被添加到demoData数组中。

您不需要初始化程序。

您确实需要一个函数来将数据添加到demoData数组。

class DemoSource: NSObject {
    static let shared = DemoSource()
    var demoData = [DataObj]()

    add(urlString: String) {
        demoData.append(DataObj(image: #imageLiteral(resourceName: "ss-1") , play_Url: URL(string: urlString), title: "title ", content: "Description"))
    }
}

然后,在您的getDatabaseReference -

func getDatabaseReference(){
    let d = DispatchGroup()
    d.enter()
    let encodedURL = (postIDRefDic["post1"]! + "/postURL")
    ref.child(encodedURL).observe(.value, with: { (snapshot) in
        if let newUrl = snapshot.value as? String {
           DemoSource.shared.add(urlString: newUrl)
        }
        d.leave()
    })
    d.notify(queue: .main){
        self.performSegue(withIdentifier: "showHome", sender: nil)
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM