【问题标题】:Trouble with delegation, my delegate is always nil, tvOS, swift 2.0委托问题,我的委托总是 nil,tvOS,swift 2.0
【发布时间】:2016-06-10 14:46:30
【问题描述】:

我正在为 tvOS 开发一个 netflix 风格的应用程序,我已经学习了一些教程,并且完成了我的 stackOverflow 研究。这非常有帮助,这实际上是我找到我正在尝试实施的委托解决方案的方式。对于我现在遇到的问题,我在这里找到的大部分内容都引用了不同的弹出视图或容器。这不完全是我的问题,所以我很难过。总的来说,我也非常喜欢新的 iOS、tvOS、Swift,我之前的大部分开发工作是 JS、AS3、Classic ASP、PHP……

直截了当:我的视图结构如图所示:view structure

我的主 ViewController 有一个类,称为 ListViewController, 我的表格视图单元格有一个名为 ListTableViewCell 的类,正如您在图像中看到的那样,引用是“rowCell”。 我有一个名为 ListViewCell 的集合视图单元的调用。

我的 ListTableViewCell 的结构如下:

import UIKit

protocol ListViewDelegate {
    func updatePreview (name: String,runtTime:Int,description:String,level:String)
}

class ListTableViewCell: UITableViewCell{
    var delegate:ListViewDelegate?
    var list:List?

    @IBOutlet weak var collectionView: UICollectionView!

    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
    }

}

extension ListTableViewCell : UICollectionViewDataSource { 

    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return 1
    }
    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        if (self.list?.MediaObjects.count != nil){
            return (self.list?.MediaObjects.count)!
        }else{
               return 0
        }

    }

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("videoCell", forIndexPath: indexPath) as! ListViewCell
            let list = self.list!
            let media = list.MediaObjects
            cell.mediaLabel.text = media[indexPath.row].name
        return cell
    }


    func collectionView(collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) {


    }

    override func shouldUpdateFocusInContext(context: UIFocusUpdateContext) -> Bool {
        let list = self.list!
        let cell: UICollectionViewCell = context.nextFocusedView as! UICollectionViewCell
        let indexPath: NSIndexPath? = self.collectionView.indexPathForCell(cell)
        if  let path = indexPath{
            let name =  list.MediaObjects[path.row].name
            let runTime = list.MediaObjects[path.row].runTime
            let description = list.MediaObjects[path.row].description
            let level = list.MediaObjects[path.row].level
            print(path.row)
            if let del = delegate {
                del.updatePreview(name,runtTime:runTime,description:description,level:level)
            }
        }

        return true
    }



    func collectionView(collectionView: UICollectionView, shouldHighlightItemAtIndexPath indexPath: NSIndexPath) -> Bool {

        return true
    }



    func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

        let playerVC = PlayerViewController()
        playerVC.videoFile = (list?.MediaObjects[indexPath.row].fileURI)!
        playerVC.playVideo()
        UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(playerVC, animated: true, completion: nil)

    }



}

委托始终为零。

这是我的 UIViewController 类的代码 -

import UIKit

class ListViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, ListViewDelegate {
    @IBOutlet weak var tableView: UITableView!

    var lists = [List]()

    @IBOutlet weak var videoDescriptionLabel: UILabel!
    @IBOutlet weak var videoLevelLabel: UILabel!
    @IBOutlet weak var videoRunTimeLabel: UILabel!
    @IBOutlet weak var videoTitleLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        let listLoader = loadLists()
        listLoader.loadData { (dataLoaded:Bool, lists:[List]) in
            if (dataLoaded == true){
                    print("complete \(self.lists.count)")
                    self.lists = lists
                    self.tableView.reloadData()
            }else {
                print("data load error")
            }

        }

        self.tableView.dataSource = self
        self.tableView.delegate = self



        // Do any additional setup after loading the view.
    }




    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return self.lists.count
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return 1
    }

    func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        let row = self.lists[section]
        return "\(row.name)"
    }

    func tableView(tableView: UITableView, canFocusRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        return false
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("rowCell") as! ListTableViewCell
        let list = self.lists[indexPath.row]
        cell.list = list

        return cell
    }

    func updatePreview(name: String,runtTime:Int,description:String,level:String) {
        print("delegage method called")
        self.videoLevelLabel.text = level
        self.videoTitleLabel.text = name
        self.videoDescriptionLabel.text = description
        self.videoRunTimeLabel.text = String(runtTime)


    }





}

这段代码还远未准备好生产,我知道,无需评论我如何处理选项等...我已经完全意识到还有其他问题需要清理。任何关于代码结构或更好方法的反馈,或者只是“你做错了”将不胜感激,但请让 cmets 保持主题。我的代码有效,我从我自己的 Parse Server 实例中提取数据,我可以浏览播放列表和视频,并以编程方式调用播放器,它们就会播放。我唯一遇到的问题是让数据冒泡回到 VC,这样我就可以更新适当的 Outlets。

我正在构建的应用永远不会是生产应用,它是概念验证和学习练习。我一般不会在这里问问题,因为我很擅长使用该网站来找到我需要的答案,但我被这个问题难住了。

The UI Screenshots

【问题讨论】:

  • 你在哪里设置代理?
  • 另外,你的代表应该被声明为weak

标签: ios swift delegates uicollectionview tvos


【解决方案1】:

您似乎没有分配您的代表:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("videoCell", forIndexPath: indexPath) as! ListViewCell
        let list = self.list!
        let media = list.MediaObjects
        cell.mediaLabel.text = media[indexPath.row].name
        cell.delegate = self // set delegate in your cellforItemAtIndexPath method
    return cell
}

【讨论】:

  • 因此,如果我尝试在该类的扩展中执行此操作,则会收到成员错误。我认为通过将课程分成上面的不同部分,这会让人感到困惑。让我将我的代码全部重新粘贴为一块。我认为你对我必须做的事情是正确的,但我不知道在哪里做。
【解决方案2】:

确保您设置了委托。对于 UITableViewController 模板,委托和数据源在界面生成器中自动设置。

尝试在界面生成器或代码中设置委托和数据源。

【讨论】:

  • 我已经为 UICollectionView 设置了委托,它的委托和它的数据源都设置为我创建的 UITableViewCell 类。我的那部分工作正常。我需要将 UITableViewCell 委托回主 ViewController,但我认为,这就是我在这里尝试做的,因为我认为这是正确的方法......但也许我需要在 UICollectionViewCell 上设置一个委托回到主 ViewController。
【解决方案3】:

所以,如果我正确理解了这个问题;您有一个具有 tableview 的视图控制器。 tableview 单元格中有一个collectionview。每当集合视图中有焦点更新时,您都希望将回调发送回视图控制器。

您所要做的就是设置您在视图控制器的 tableview cellForRow 方法中创建的委托变量。

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ListTableViewCell.self), for: indexPath) as! ListTableViewCell

        cell.delegate = self /// Setting the delegate so that view controller gets the callback for focus update

        return cell
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-05
    • 2020-06-13
    • 2018-12-31
    • 2013-01-06
    相关资源
    最近更新 更多