【问题标题】:UICollectionView Array index out of rangeUICollectionView 数组索引超出范围
【发布时间】:2014-07-08 03:33:58
【问题描述】:

我正在尝试在 Swift 中创建一个非常基本的集合视图控制器,它允许我列出一些数字,当我点击其中一个时,它会将我带到一个详细信息页面,该页面简单地说明(在标签中)你是什么数字轻拍。

故事板: 我的故事板有一个作为根的导航控制器和一个加载的集合视图控制器。这包含一个单元格,其标识符为单元格。此单元格有一个按钮,用作详细信息页面的 segue。我已将数据源分配为指向自身(控件单击视图控制器的行以建立数据源)并且我已将 segue 唯一标识为 showDetail。

当我加载应用程序时,它会显示我的按钮 7 次,但是当我单击其中任何一个时,我会在下面的行中得到一个超出范围的索引:

这是我的代码:

import Foundation
import UIKit


class WeekCollectionView : UICollectionViewController
{
    override func collectionView(collectionView: UICollectionView!, numberOfItemsInSection section: Int) -> Int
    {
        return 7
    }

    override func collectionView(collectionView: UICollectionView!, cellForItemAtIndexPath indexPath: NSIndexPath!) -> UICollectionViewCell!

    {
      let cell: ShiftCell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as ShiftCell
        return cell;
    }

    override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!)

    {    
        if (segue.identifier == "showDetail") {
           **//CRASHES ON THIS LINE BELOW FOR THE ARRAY [0]** 
            let indexPaths: NSArray = self.collectionView.indexPathsForSelectedItems()[0] as NSArray
            let destinationViewController = segue.destinationViewController as DetailViewController
            //var someNumber = images[indexPath.row]
            destinationViewController.mySpecialID = 1 //replace this with someNumber, always set 1 for now as a test
        }
    } 
}

我的单元格类(上图)很简单:

class ShiftCell: UICollectionViewCell { 
   init(frame: CGRect) {
      super.init(frame: frame)
   }

  init(coder aDecoder: NSCoder!) {
       super.init(coder: aDecoder)
   }

}

我真的不确定我做错了什么 - 也许我的故事板中需要发生其他事情?我遵循了来自苹果的教程(在objective-c中),它运行良好,如果我没记错的话,所有的代码都是相同的!

我真的被困在这里,如果有人能指出我正确的方向,非常感谢! :)

【问题讨论】:

    标签: ios ios7 swift xcode-storyboard


    【解决方案1】:

    您遇到此崩溃是因为没有选定的项目。您在单元格顶部有一个按钮,它阻止触摸到达单元格以实际选择它。您将不得不想出一种不同的方法来识别每个按钮所代表的行。一个常见的模式是使用按钮的tag 属性。这可以存储任意整数以帮助您识别视图。

    因此,在collectionView:cellForItemAtIndexPath 中,您应该将按钮的标签设置为当前索引:

    override func collectionView(collectionView: UICollectionView!, cellForItemAtIndexPath indexPath: NSIndexPath!) -> UICollectionViewCell!
    {
        let cell: ShiftCell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as ShiftCell
        cell.myButton.tag = indexPath.item
        return cell;
    }
    

    那么我相信segue 的sender 将是按钮。您可以从中获取索引:

    override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!)
    {    
        if (segue.identifier == "showDetail") {
            var possibleIndex : Int?
            if let button = sender as? UIButton {
                possibleIndex = button.tag
            }
    
            if let index = possibleIndex {
                // ...
            }
        }
    }
    

    注意:我不肯定发件人将成为按钮,因为我通常通过没有故事板的代码来做事。如果 sender 不是按钮,您始终可以使用“旧时尚方式”将按钮连接到 Storyboard 中的视图控制器上的方法,而不是使用 segue。然后,您可以在代码中创建新的控制器,然后根据需要显示它。

    【讨论】:

    • 非常感谢 - 我打算稍后再试。所以如果我点击按钮,然后向下滚动到“标签”,我可以给它一个#,比如 200 之类的?就这样?这个“中继器”会让每个按钮都有一个 200 的标签吗?
    • 所以我试了一下,它仍然崩溃(我单击单元格内的按钮,并将标签设置为 198 之类的东西).. 我是否需要以某种方式给每个按钮一个唯一的标签它重复?就像即使我在单元格中只有一个按钮,但随着每次迭代的发生,我是否需要以编程方式给按钮一个唯一的标签?
    • @user3379785 我用一些示例代码更新了我的答案。您确实需要为每个按钮设置一个唯一的标签。更具体地说,您希望单元格上的标记与显示它的索引完全匹配。
    • 你是最棒的——感谢你的帮助。我明白了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多