Как получить доступ к определенной ячейке в UICollectionView после прокрутки при загрузке страницы? - PullRequest
0 голосов
/ 06 сентября 2018

Я пытаюсь построить временную шкалу так:

enter image description here

Каждая ячейка на временной шкале представляет месяц, поэтому май - последняя ячейка в горизонтальном 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 ]

0 голосов
/ 07 сентября 2018

Я бы рекомендовал переместить код прокрутки на 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)
}
0 голосов
/ 06 сентября 2018

Не устанавливайте эти строки на их текущем месте

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 не асинхронный

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...