Невозможно загрузить UICollectionView с собственным IndexPath, также IndexPath добавляется случайным образом при печати его в ячейке для элемента по адресу: - PullRequest
0 голосов
/ 20 января 2019

Я пытаюсь создать приложение Gallery, очень похожее на то, которое уже встроено в устройства iOS. Я добавил несколько случайных изображений в качестве исходных данных и настроил два контроллера вида, оба из которых являются видами коллекций, но первый отображает все доступные изображения, а второй - каждый отдельно. Проблема начинается, когда я перехожу ко второму контроллеру вида (где вы можете увидеть отдельное изображение), когда я пытаюсь прокрутить горизонтально, всегда появляется одна и та же фотография, она никогда не изменяется или перебирает imagesArray (который предоставляет источник для данных UICollectionView Источник). Несмотря на то, что в UIImageArray есть четыре изображения, при переходе ко второму контроллеру просмотра я могу прокручивать назад и вперед, но всегда появляется одна и та же фотография. Я ожидаю, что он будет вести себя так, что пользователь сможет прокручивать вперед и назад и видеть каждое изображение в массиве (то же самое в приложении Галерея iOS)

Приложение должно загружать изображение, выбранное пользователем, оно делает, но когда я прокручиваю, оно остается на том же изображении. Приложение точно знает, какое изображение извлечь в imagesArray с помощью indexPath, заданного в первом контроллере представления и переданного второму в методе prepareForSegue, когда я это делаю, показывается выбранное пользователем изображение, но только это изображение. Эта ссылка хранится в переменной с именем «sentContentOffSet», которая ссылается на indexPath предыдущего ViewController. Затем, чтобы заполнить данные представления коллекции второго контроллера представления, я использую passContentOffSet.item, однако возникает проблема, упомянутая выше. Я изменил это просто на indexPath.item, и теперь представление коллекции может прокручивать все доступные изображения, но оно всегда начинается с первого изображения, а не с изображения, выбранного пользователем.

Контроллер первого вида (где все изображения отображаются вертикально)

class CollectionViewController: UIViewController, UINavigationBarDelegate, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout  {
    let context =   (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

    @IBOutlet weak var collectionView: UICollectionView!
    struct Storyboard {
        static let photoCell = "PhotoCell"
        static let sectionHeaderView = "SectionHeaderView"
        static let showDetailVC = "ShowImageDetail"

        static let leftAndRightPaddings: CGFloat = 2.0
        static let numberOfItemsPerRow: CGFloat = 3.0


    }

    var images:[UIImage] = [UIImage(named: "facebook")!, UIImage(named: "pinterest")!, UIImage(named: "linkedin")!, UIImage(named: "amazon")! ]

    @IBOutlet weak var toolBar: UIToolbar!

    var selectedIndexPath:IndexPath = IndexPath()

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationItem.backBarButtonItem?.tintColor = UIColor.white

        collectionView.delegate = self
        collectionView.reloadData()
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let collectionViewWidth = collectionView.frame.width
        let itemWidth = (collectionViewWidth - Storyboard.leftAndRightPaddings) / Storyboard.numberOfItemsPerRow
        return CGSize(width: itemWidth, height: itemWidth)
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return images.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photo", for: indexPath) as! CollectionViewCell

        let selectedItem = images[indexPath.row]

        cell.userImageView.image = selectedItem

        return cell
    }


    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        selectedIndexPath = indexPath
        performSegue(withIdentifier: "goToDescription", sender: self)
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "goToDescription" {

            let destinationVC = segue.destination as! ImagePreviewVC
            destinationVC.images = images
            destinationVC.passedContentOffset = selectedIndexPath

        }
    }
}

Теперь, контроллер второго вида, где приложение должно показывать пользователю индивидуальное изображение, которое выбрал пользователь, а также иметь возможность прокрутки по горизонтали, чтобы увидеть другие изображения

class ImagePreviewVC: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout  {
    var myCollectionView: UICollectionView!
    var imgArray = [UIImage]()
    var passedContentOffset = IndexPath()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        self.view.backgroundColor=UIColor.black

        let layout = UICollectionViewFlowLayout()
        layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        layout.minimumInteritemSpacing=0
        layout.minimumLineSpacing=0
        layout.scrollDirection = .horizontal

        myCollectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
        myCollectionView.delegate=self
        myCollectionView.dataSource=self
        myCollectionView.register(ImagePreviewFullViewCell.self, forCellWithReuseIdentifier: "Cell")
        myCollectionView.isPagingEnabled = true
        myCollectionView.scrollToItem(at: passedContentOffset, at: .left, animated: true)

        self.view.addSubview(myCollectionView)

        myCollectionView.autoresizingMask = UIViewAutoresizing(rawValue: UIViewAutoresizing.RawValue(UInt8(UIViewAutoresizing.flexibleWidth.rawValue) | UInt8(UIViewAutoresizing.flexibleHeight.rawValue)))
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return imgArray.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell=collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! ImagePreviewFullViewCell
        cell.imgView.image=imgArray[indexPath.row]
        return cell
    }

    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()

        guard let flowLayout = myCollectionView.collectionViewLayout as? UICollectionViewFlowLayout else { return }

        flowLayout.itemSize = myCollectionView.frame.size

        flowLayout.invalidateLayout()

        myCollectionView.collectionViewLayout.invalidateLayout()
    }

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        let offset = myCollectionView.contentOffset
        let width  = myCollectionView.bounds.size.width

        let index = round(offset.x / width)
        let newOffset = CGPoint(x: index * size.width, y: offset.y)

        myCollectionView.setContentOffset(newOffset, animated: false)

        coordinator.animate(alongsideTransition: { (context) in
            self.myCollectionView.reloadData()

            self.myCollectionView.setContentOffset(newOffset, animated: false)
        }, completion: nil)
    }
}

Класс ячейки:

class ImagePreviewFullViewCell: UICollectionViewCell, UIScrollViewDelegate {
    var scrollImg: UIScrollView!
    var imgView: UIImageView!

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

        scrollImg = UIScrollView()
        scrollImg.delegate = self
        scrollImg.alwaysBounceVertical = false
        scrollImg.alwaysBounceHorizontal = false
        scrollImg.showsVerticalScrollIndicator = true
        scrollImg.flashScrollIndicators()

        scrollImg.minimumZoomScale = 1.0
        scrollImg.maximumZoomScale = 4.0

        let doubleTapGest = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTapScrollView(recognizer:)))
        doubleTapGest.numberOfTapsRequired = 2
        scrollImg.addGestureRecognizer(doubleTapGest)

        self.addSubview(scrollImg)

        imgView = UIImageView()
        imgView.image = UIImage(named: "user3")
        scrollImg.addSubview(imgView!)
        imgView.contentMode = .scaleAspectFit
    }

    @objc func handleDoubleTapScrollView(recognizer: UITapGestureRecognizer) {
        if scrollImg.zoomScale == 1 {
            scrollImg.zoom(to: zoomRectForScale(scale: scrollImg.maximumZoomScale, center: recognizer.location(in: recognizer.view)), animated: true)
        } else {
            scrollImg.setZoomScale(1, animated: true)
        }
    }

    func zoomRectForScale(scale: CGFloat, center: CGPoint) -> CGRect {
        var zoomRect = CGRect.zero
        zoomRect.size.height = imgView.frame.size.height / scale
        zoomRect.size.width  = imgView.frame.size.width  / scale
        let newCenter = imgView.convert(center, from: scrollImg)
        zoomRect.origin.x = newCenter.x - (zoomRect.size.width / 2.0)
        zoomRect.origin.y = newCenter.y - (zoomRect.size.height / 2.0)
        return zoomRect
    }

    func viewForZooming(in scrollView: UIScrollView) -> UIView? {
        return self.imgView
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        scrollImg.frame = self.bounds
        imgView.frame = self.bounds
    }

    override func prepareForReuse() {
        super.prepareForReuse()
        scrollImg.setZoomScale(1, animated: true)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

Я ожидаю, что пользователь действительно может выбрать изображение в первом контроллере представления, и это изображение будет отображаться отдельно во втором контроллере представления, а также то, что оттуда пользователь может провести пальцем вправо или влево и увидеть другие изображения в массиве, так же, как приложение iOS Gallery.

...