Popover, присоединенный к ячейке в UICollectionView, перемещается, когда вызывается ReloadData этого представления коллекции - PullRequest
0 голосов
/ 14 февраля 2020

У меня есть UICollectionView, на который пользователь может щелкнуть, и он показывает всплывающее окно, прикрепленное к нажатой ячейке. В iOS 12 всплывающее окно оставалось в том же источнике (x, y или ячейка), если данные перезагрузки вызывались или нет, но в iOS 13 всплывающее окно перемещается между ячейками, когда данные перезагрузки представления сбора

Следите за видео о поведении в iOS 13: https://vimeo.com/385021234

Презентация выполняется с использованием следующего кода:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    guard let cell = collectionView.cellForItem(at: indexPath) else {
        return
    }

    presentPopover(from: self, cell: cell)
}

func presentPopover(from view: UIViewController, cell: UIView) {
    let popoverView = PopoverViewController(nibName: "PopoverViewController", bundle: nil)
    let popover: UIPopoverPresentationController = popoverView.popoverPresentationController!

    popover.sourceRect = cell.bounds
    popover.sourceView = cell

    view.present(popoverView, animated: true, completion: nil)
}

А PopoverViewController использует modalPresentationStyle = .popover

Кто-нибудь имел эту проблему раньше в iOS 13? Наше приложение работало нормально в iOS 11 и 12.

У меня есть пример такого поведения в следующем git хранилище: https://github.com/diegodossantos95/UICollectionViewPopoverBug

Шаги для воспроизведения в хранилище:

  1. Нажмите на ячейку коллекции

  2. Откроется всплывающее окно

  3. Подождите для перезагрузки данных

Спасибо,

D iego.

Ответы [ 2 ]

0 голосов
/ 14 февраля 2020

Вместо того, чтобы прикреплять поповер к ячейке, которая, как вы можете гарантировать, не будет снята, вы можете использовать временный UIView, созданный из фрейма ячейки, а затем присоединить к нему поповер. Вот соответствующий код для выполнения sh этого.

class ViewController: UIViewController {
    var timer = Timer()

    var popOverTempView = UIView()

    @IBOutlet weak var collectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()
        timer = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(reloadData), userInfo: nil, repeats: true)
        self.collectionView.addSubview(popOverTempView)
        popOverTempView.isHidden = true
        popOverTempView.backgroundColor = .clear
    }

}

extension ViewController: UICollectionViewDelegate {

    func presentPopover(from view: UIViewController, cell: UIView) {
        let popoverView = PopoverViewController(nibName: "PopoverViewController", bundle: nil)
        let popover: UIPopoverPresentationController = popoverView.popoverPresentationController!

        popoverView.delegate = self

        popOverTempView.frame = cell.frame
        popOverTempView.isHidden = false
        popover.sourceRect = popOverTempView.bounds
        popover.sourceView = popOverTempView

        view.present(popoverView, animated: true, completion: nil)

    }

}

extension ViewController: PopoverViewControllerDelegate {
    func willDismissPopover() {
        popOverTempView.isHidden = true
    }
}

protocol PopoverViewControllerDelegate {
    func willDismissPopover()
}

class PopoverViewController: UIViewController {

    var delegate: PopoverViewControllerDelegate?

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        delegate?.willDismissPopover()
    }
}
0 голосов
/ 14 февраля 2020

Когда вы вызываете reloadData, это заставляет представление коллекции отбрасывать любые видимые в настоящее время элементы (включая заполнители) и воссоздавать элементы на основе текущего состояния объекта источника данных.

Разница между кадрами ячеек до и после перезагрузки данных:

  - some : <UICollectionViewCell: 0x7fd8abd02190; frame = (73.5 10; 50 50); clipsToBounds = YES; hidden = YES; opaque = NO; layer = <CALayer: 0x600001b50e20>>
  - some : <UICollectionViewCell: 0x7fd8abd02190; frame = (519.5 10; 50 50); clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x600001b50e20>>

, если вам нужно изменить только один или несколько элементов itens в коллекции, попробуйте использовать:

func reloadItems(at: [IndexPath])
...