【问题标题】:Passing data from CollectionView to DetailVC in Swift 4在 Swift 4 中将数据从 CollectionView 传递到 DetailVC
【发布时间】:2019-10-12 15:03:39
【问题描述】:

我的CollectionView 应该将一个类模型传递给DetailViewController,但是当我点击一个单元格时,我得到了 nil 错误。

致命错误:在隐式展开时意外发现 nil 可选值

CollectionViewController 以编程方式嵌入在TabBarController 上。

收藏夹视图


func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return soundArray.count
    }

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SoundCell", for: indexPath) as? SoundCell {
    let SoundClass = soundArray[indexPath.row]
    cell.updateUI(SoundClass: SoundClass)
    return cell

    } else {
    return UICollectionViewCell()
    }
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    self.performSegue(withIdentifier: "seguetosound", sender: self)

  }

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    if segue.identifier == "seguetosound" {
    if let detailVC = segue.destination as? DetailSecondVC
    let sound = sender as? SoundClass { 
    detailVC.SoundClass = sound 

    }
 }

细节视图控制器

class DetailSecondVC: UIViewController, UIWebViewDelegate {

private var _SoundClass: SoundClass!

var SoundClass: SoundClass {
        get {
            return _SoundClass
        } set {
            _SoundClass = newValue
        }
    }

你知道我在这里缺少什么吗?我用一个简单的白屏测试了 segue,它可以工作,但是当我尝试传递数据时,它失败了。

【问题讨论】:

  • 显示 cellForItem 方法
  • 好的!我更新了它
  • 非常有意义。你说sender: self。然后你说let sound = sender as? SoundClass。所以如果self 不是一个SoundClass,sound 将是nil。但是self 不是 SoundClass;它是一个 CollectionViewController。
  • 请不要给变量名以大写字母开头。那是错误的。并且不要调用变量SoundClass 甚至soundClass。它是一个变量,而不是一个类。而且你不能“通过一门课”。
  • @matt 那么谁应该是发件人?我更改了变量名,但这并没有解决问题;)

标签: ios swift uiviewcontroller segue uistoryboardsegue


【解决方案1】:

正确的做法是这样。首先,弄清楚你想如何触发 segue。一种选择是,在didSelect 中,在代码中触发 segue:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    self.performSegue(withIdentifier: "seguetosound", sender: self)
}

但更好的是,完全删除didSelectItemAt 并让情节提要中的segue 来自单元格。这样,当用户点击单元格时,会自动触发 segue。

然后,在prepare 中,找出选择的索引路径,并从模型中提取数据并将其传递给目标视图控制器(这可能无法编译,因为你的变量名太糟糕了,我可以'不阅读您的代码,但通常这是正确的方法):

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "DetailSecondVC" {
        if let detailVC = segue.destination as? DetailSecondVC {
            if let paths = collectionView?.indexPathsForSelectedItems {
                let row = paths[0].row
                detailVC.SoundClass = SoundClasss[row]
            }
        }
    }
}

【讨论】:

  • 它编译,但是当我点击单元格时,我仍然得到同样的错误,并且变量为零。没有通过。很抱歉变量名,它们是经过多次试验和错误的结果
  • 好吧,我刚刚在我自己的项目中尝试过这个并且它有效,所以可能还有其他问题是你没有告诉我们的。
  • 谢谢,是的,好像是别的东西。我会发现
  • 谢谢@matt,现在已经解决了,每次给我的变量命名都会记住这个帖子
【解决方案2】:

已编辑:我认为解决方案是从视图控制器而不是从单元格进行转场,但正如马特所说,从单元格中转场是正确的,但我只需要删除 didSelectItemAt

【讨论】:

  • 从牢房中分离是正确的。问题是,在这种情况下,您不能触发didSelectItemAt 中的转场,因为现在您触发了转场两次。事实上,您应该保持原样,只需删除您对didSelectItemAt 的实现。
  • 知道了,所以问题是我做了两次segue!太感谢了!我将编辑我的评论
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-14
  • 1970-01-01
  • 2015-03-19
  • 2016-07-26
相关资源
最近更新 更多