मैं विभिन्न कोशिकाओं के लिए परिवर्तनीय ऊंचाई के साथ UICollectionView रखने के लिए निम्न कोड का उपयोग कर रहा हूं:

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

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

        totalItems -= 1

        collectionView.deleteItems(at: [indexPath])
        collectionView.collectionViewLayout.invalidateLayout()
    }
}

extension InviteViewController : PinterestLayoutDelegate {

    // 1. Returns the cell height
    func collectionView(_ collectionView: UICollectionView, heightForPhotoAtIndexPath indexPath:IndexPath) -> CGFloat {
        print("have: ", indexPath.item)
        if(indexPath.item % 3 == 0) {
            return 150
        } else if(indexPath.item % 3 == 1) {
            return 200
        } else {
            return 250
        }
    }
}

हालांकि मैं देखता हूं कि UICollectionViewCell को हटाने के बाद लेआउट अपडेट नहीं होता है और मुझे त्रुटियां मिलती हैं:

*** न आया हुआ अपवाद 'NSInternalInconsistencyException' के कारण ऐप को समाप्त करना, कारण: 'UICollectionView को एक इंडेक्स पथ वाले सेल के लिए लेआउट विशेषताएँ प्राप्त हुईं जो मौजूद नहीं हैं: {लंबाई = 2, पथ = 0 - 7}'

मैं फंस गया हूं और यह समझने में असमर्थ हूं कि ऐसा क्यों होता है और इसे कैसे हल किया जाए। कृपया मुझे उसी का समाधान खोजने में मदद करें। धन्यवाद।

यदि आप मेरे द्वारा उपयोग की गई लेआउट फ़ाइल को देखना चाहते हैं, तो कृपया यहां देखें:

import UIKit

protocol PinterestLayoutDelegate: class {
    // 1. Method to ask the delegate for the height of the image
    func collectionView(_ collectionView:UICollectionView, heightForPhotoAtIndexPath indexPath:IndexPath) -> CGFloat
}

class PinterestLayout: UICollectionViewLayout {
    //1. Pinterest Layout Delegate
    weak var delegate: PinterestLayoutDelegate!

    //2. Configurable properties
    fileprivate var numberOfColumns = 2
    fileprivate var cellPadding: CGFloat = 3

    //3. Array to keep a cache of attributes.
    fileprivate var cache = [UICollectionViewLayoutAttributes]()

    //4. Content height and size
    fileprivate var contentHeight: CGFloat = 0

    fileprivate var contentWidth: CGFloat {
        guard let collectionView = collectionView else {
            return 0
        }
        let insets = collectionView.contentInset
        return collectionView.bounds.width - (insets.left + insets.right)
    }

    override var collectionViewContentSize: CGSize {
        return CGSize(width: contentWidth, height: contentHeight)
    }

    override func prepare() {
        // 1. Only calculate once
        guard cache.isEmpty == true, let collectionView = collectionView else {
            return
        }
        // 2. Pre-Calculates the X Offset for every column and adds an array to increment the currently max Y Offset for each column
        let columnWidth = contentWidth / CGFloat(numberOfColumns)
        var xOffset = [CGFloat]()
        for column in 0 ..< numberOfColumns {
            xOffset.append(CGFloat(column) * columnWidth)
        }
        var column = 0
        var yOffset = [CGFloat](repeating: 0, count: numberOfColumns)

        // 3. Iterates through the list of items in the first section
        for item in 0 ..< collectionView.numberOfItems(inSection: 0) {

            let indexPath = IndexPath(item: item, section: 0)

            // 4. Asks the delegate for the height of the picture and the annotation and calculates the cell frame.
            let photoHeight = delegate.collectionView(collectionView, heightForPhotoAtIndexPath: indexPath)
            let height = cellPadding * 2 + photoHeight
            let frame = CGRect(x: xOffset[column], y: yOffset[column], width: columnWidth, height: height)
            let insetFrame = frame.insetBy(dx: cellPadding, dy: cellPadding)

            // 5. Creates an UICollectionViewLayoutItem with the frame and add it to the cache
            let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
            attributes.frame = insetFrame
            cache.append(attributes)

            // 6. Updates the collection view content height
            contentHeight = max(contentHeight, frame.maxY)
            yOffset[column] = yOffset[column] + height

            column = column < (numberOfColumns - 1) ? (column + 1) : 0
        }
    }

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {

        var visibleLayoutAttributes = [UICollectionViewLayoutAttributes]()

        // Loop through the cache and look for items in the rect
        for attributes in cache {
            if attributes.frame.intersects(rect) {
                visibleLayoutAttributes.append(attributes)
            }
        }
        return visibleLayoutAttributes
    }

    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        return cache[indexPath.item]
    }

}

मैंने इसका अनुसरण किया: -कस्टम-लेआउट-ट्यूटोरियल-पिंटरेस्ट

1
Enrik Qaz 23 अक्टूबर 2018, 13:49

1 उत्तर

सबसे बढ़िया उत्तर
override func prepare() {
    // 1. Only calculate once
    guard cache.isEmpty == true, let collectionView = collectionView else {
        return
    }

इस भाग में guard cache.isEmpty == true, हटाएं। यह काम करता है।

extension CategoryPageVC: PinterestLayoutDelegate {
    func collectionView(_ collectionView: UICollectionView,
                        heightForPhotoAtIndexPath indexPath:IndexPath) -> CGFloat {

let rate = self.categoryData[indexPath.item].image.size.width / self.collectionView.frame.size.width * 2
        return self.categoryData[indexPath.item].image.size.height / rate
    }
}
0
Ali Ihsan URAL 23 अक्टूबर 2018, 17:05