首页 文章

如何在页面加载后滚动后访问UICollectionView中的特定单元格?

提问于
浏览
0

我正在尝试 Build 一个如此的时间表:

enter image description here

时间轴中的每个单元格表示一个月,因此May是水平collectionView中的最后一个单元格 . 我想要的是当collectionView加载时,它会自动滚动到可能,如果它尚未可见,则调用单元格上的特定函数来绘制箭头 . 我用来尝试这样做的代码如下 .

override func viewDidLoad() {
    super.viewDidLoad()
    self.timeline.register(UINib(nibName: "TimelineMonthViewCell", bundle: nil), forCellWithReuseIdentifier: "TimelineMonthViewCell")
    self.collectionView.register(UINib(nibName: "PostCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "PostCollectionViewCell")
    pageControl.hidesForSinglePage = true
    self.navigationItem.largeTitleDisplayMode = .never

    UserService.posts(for: User.current,tagString: self.selectedTagTitles.first!) { (postStuff) in

        self.posts = postStuff.0
        self.postIds = postStuff.1
        self.timeline.dataSource = self
        self.collectionView.dataSource = self
        self.timeline.delegate = self
        self.collectionView.delegate = self
        self.firstPostDate = self.posts.first?.timeStamp
        self.currentPostDate = self.posts.last?.timeStamp
    }
}

override open func viewDidAppear(_ animated: Bool) {

    super.viewDidAppear(animated)

    let indexToScrollTo = IndexPath(row: self.posts.count - 1, section: 0)
    self.collectionView.scrollToItem(at: indexToScrollTo, at: .left, animated: false)
    let firstPostDate = self.posts.first?.timeStamp
    let diff = self.posts.last?.timeStamp.months(from: (firstPostDate?.startOfMonth())!)
    //self.currentPostMonth = diff
    let monthCellIndexPath = IndexPath(row: diff!, section: 0)
    self.timeline.scrollToItem(at: monthCellIndexPath, at: .centeredHorizontally, animated: false)
    let months = self.posts.last?.timeStamp.months(from: (self.posts.first?.timeStamp.startOfMonth())!)
    print("cells are",self.timeline.indexPathsForVisibleItems)
    print(months,"cell months")
    if let optionalCell = self.timeline.cellForItem(at: IndexPath(row: months!, section: 0)) {
        let cell = optionalCell as! TimelineMonthViewCell
        let day = Calendar.current.component(.day, from: self.currentPostDate!)
        cell.drawArrow(day: day)
    } else {
        print("cell out of range")
    }
}

这几乎可以解决两个问题 .

首先,初始单元格在自动滚动到最后一个单元格之前闪烁 . 我想这是因为我使用viewDidAppear而不是viewWillAppear . 但是,当我使用viewWillLoad时,我的应用程序崩溃并出现错误: Thread 1: EXC_BAD_ACCESS (code=1, address=0xfffffffffffffff8)

其次,打印的self.timeline.indexPathsForVisibleItems是:[[0,0],[0,1],[0,2],[0,3],[0,4]] . 所以它看着它刚刚滚动到的前5个而不是最后5个 . 然后它找不到单元格:“单元格超出范围”,因为索引大约是28(最后一个单元格) .

那么如何让它自动滚动到最后一个单元格并正确找到它?

2 回答

  • 1

    不要将这些线设置在当前位置

    self.timeline.dataSource = self
    self.collectionView.dataSource = self
    self.timeline.delegate = self
    self.collectionView.delegate = self
    

    可能会更好地在 viewDidLoad 之上,以便在加载vc时利用第一次自动重新加载,也可以在它们的位置插入

    self.timeline.reloadData()
    self.collectionView.reloadData()
    

    你可以在里面插入滚动代码

    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {  }
    

    或者在 ViewDidAppear 内,如果你当前的for循环不是异步的

  • 0

    我建议将滚动代码移动到 viewWillAppear . 这样就可以在显示视图之前完成,但是在所有内容都可以查看之后 .

    override open func viewWillAppear(_ animated: Bool) {
    
        super.viewWillAppear(animated)
    
        let indexToScrollTo = IndexPath(row: self.posts.count - 1, section: 0)
        self.collectionView.scrollToItem(at: indexToScrollTo, at: .left, animated: false)
        let firstPost = self.posts.first?.timeStamp
        let firstOfFirstMonth = firstPost?.startOfMonth()
        let diff = self.posts.last?.timeStamp.months(from: firstOfFirstMonth!)
        //self.currentPostMonth = diff
        let monthCellIndexPath = IndexPath(row: diff!, section: 0)
        self.timeline.scrollToItem(at: monthCellIndexPath, at: .centeredHorizontally, animated: false)
    }
    

相关问题