Swift |没有故事板的 UICollectionView 显示不正确的数据

Swift | UICollectionView without storyboard shows incorrect data

我正在构建一个具有包含三个项目的 UICollectionView 的应用程序。每个项目都占据了整个屏幕的宽度,并显示了一个计时器,该计时器为我们的巴士在每个位置的下一次出发时间倒计时。

每个项目包含 1) 出发地址,2) 一个字符串 "Next shuttle leaves at time",以及 3) 倒计时到下一个出发时间的计时器,格式为 00:00:00。

项目 1 和 2 按预期显示,但当我到达项目 3 时,出发地址和字符串是正确的,但计时器显示单元格 1 的时间而不是单元格 3 的时间。

我将 UICollectionView 设置为:

func setupCollectionView() {    
    let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
    layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    layout.itemSize = frame.size
    layout.minimumLineSpacing = 0
    layout.minimumInteritemSpacing = 0
    layout.scrollDirection = UICollectionViewScrollDirection.Horizontal
    let collFrame:CGRect = CGRectMake(0, 0, self.frame.width, self.frame.height)
    collectionView = UICollectionView(frame: collFrame, collectionViewLayout: layout)
    collectionView!.dataSource = self
    collectionView!.delegate = self
    collectionView!.registerClass(NextShuttleCell.self, forCellWithReuseIdentifier: "cell")
    collectionView!.backgroundColor = UIColor.whiteColor()
    collectionView!.pagingEnabled = true
    collectionView!.scrollIndicatorInsets = UIEdgeInsetsZero
    collectionView!.layer.borderWidth = 0
    collectionView!.layer.borderColor = UIColor.clearColor().CGColor
    self.addSubview(collectionView!)

}

并使用以下方法创建项目:

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

    let cell:NextShuttleCell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! NextShuttleCell

    switch(indexPath.row) {
    case 0:
        cell.setCellColor(help.darkAccent1())
        cell.setLocationLabel("Auckland, Victoria Street")
        cell.schedule = getScheduleFor("Victoria Street")
    case 1:
        cell.setCellColor(help.darkAccent2())
        cell.setLocationLabel("Wellington, Airedale Street")
        cell.schedule = getScheduleFor("Airedale Street")
    case 2:
        cell.setCellColor(help.darkAccent3())
        cell.setLocationLabel("Airport, Auckland")
        cell.schedule = getScheduleFor("Auckland Airport")
    default: break
    }

    return cell

}

实例化此视图时,它会从 Parse.com 检索时间表。 getScheduleFor 函数然后遍历此计划,returns 相关位置计划对象到自定义单元格。

我知道 getScheduleFor 函数工作正常,因为它为前两项提取了正确的信息,如果我更改了项的顺序(例如,将项 3 的代码与项 1 交换,那么正确的数据显示在第 1 项中,但第 3 项不正确。

另请注意,只有第 3 项的计时器不正确,其余信息是正确的,这也是从计划对象中提取的 - 所以我知道它提取的是正确的数据。

我还将它移到了 UITableView 中,它显示了正确的数据,所以这似乎与 UICollectionView 管理它的项目的方式有关。

编辑:

我正在使用自定义 UICollectionViewCell 并使用以下方法对其进行初始化:

override init(frame: CGRect) {
super.init(frame: frame)
    initTimer()
}

这将获取下一次穿梭时间并初始化一个计时器以更新倒计时标签。

func initTimer() {        
    nextShuttleTime = getNextShuttleTime()
    timeTillNextShuttle = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "updateTime", userInfo: nil, repeats: true)
}

然后,它使用以下方法获取时间:

func updateTime() {

    let nextShuttleAt:NSTimeInterval = NSTimeInterval(nextShuttleTime.timeIntervalSinceNow)
    let currentTime:NSTimeInterval = NSTimeInterval(NSDate().timeIntervalSinceNow)
    let timeLeft:NSTimeInterval = nextShuttleAt - currentTime

    if timeLeft >= 0 {
        let seconds = timeLeft
        timeLabel.text = "\(stringFromTimeInterval(seconds))"
        self.updateNextShuttleLabel()
    } else {
        timeTillNextShuttle.invalidate()
        initTimer()
    }

}

可行的解决方案:

根据评论,我停止将 getNextShuttleTime() 分配给变量,而是在 updateTimer() 函数中调用它。更新如下:

func initTimer() {        
    timeTillNextShuttle = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "updateTime", userInfo: nil, repeats: true)
}

func updateTime() {

    let nextShuttleAt:NSTimeInterval = NSTimeInterval(getNextShuttleTime().timeIntervalSinceNow)
    let currentTime:NSTimeInterval = NSTimeInterval(NSDate().timeIntervalSinceNow)
    let timeLeft:NSTimeInterval = nextShuttleAt - currentTime

    if timeLeft >= 0 {
        let seconds = timeLeft
        timeLabel.text = "\(stringFromTimeInterval(seconds))"
        self.updateNextShuttleLabel()
    } else {
        timeTillNextShuttle.invalidate()
        initTimer()
    }

}

您的 NextShuttleCell 对象将被重新使用,因此您需要确保在分配单元格时更新所有内容 - 您不能依赖 init() 因为它只会被称为第一次分配单元格。

而不是将 nextShuttleTime 变量存储在 initTimer() 中,您可以在 updateTime 中调用 getNextShuttleTime() - 这样您将始终获得正确的时间。