将项目添加到节中时,UICollectionView显示的项目不正确(快速)

时间:2018-12-08 11:06:26

标签: ios swift uicollectionview

当我向第1节添加项目并将项目的节从第1节更改为第2节时,我的UICollectionview可以正常工作。但是,如果执行以下操作,则项目开始显示不正确:

  1. 将项目添加到第1节
  2. 将项目从第1部分移至第2部分
  3. 在第1节中添加新项(<->,这里数据中断,并且收集视图开始两次显示一项)

以下将其称为“故障场景”。

几天来,我一直在努力理解这个问题的原因。我确信这是基础知识,但以目前的知识水平,我仍然无法弄清楚。我可以用一个部分来实现UICollectionviews,但是我依靠UICollectionViews上的Raywenderlich教程来弄清楚如何实现多个部分,并且我对示例代码并不完全满意。我依赖的教程在此处(尽管我认为是在付费专区后面):(https://www.raywenderlich.com/6308-beginning-collection-views/lessons/16)。

这是UICollectionview在我的应用程序中的工作方式的描述,以及代码的关键部分。


加载该应用程序后,datasource.swift中的一个函数将运行一个填充UICollectionview的函数。

这是代码:

    private func loadPicturesFromDisk() -> [Picture] {
    sections.removeAll(keepingCapacity: false)

    let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
    let archiveURL = documentsDirectory.appendingPathComponent("pictures").appendingPathExtension("plist")
    let propertyListDecoder = PropertyListDecoder()

    if let retrievedPicturesData = try? Data(contentsOf: archiveURL), let decodedPictures = try? propertyListDecoder.decode(Array<Picture>.self, from: retrievedPicturesData) {
        for picture in decodedPictures {
            let pictureName = picture.pictureName
            print("The pictureName in loadPicturesFromDisk = \(pictureName), the pictureCategory is = \(picture.pictureCategory)")
            let pictureCategory = picture.pictureCategory


            if !sections.contains(pictureCategory) {
                sections.append(pictureCategory)
            }

            let newPicture = Picture(picture: pictureName, category: pictureCategory)
            pictures.append(newPicture)

        }

        print("Enumerating through pictures in loadPicturesFromDisk")
        enumerateThroughPictures(pictures: pictures)


        return pictures

    } else {
        return []
    }
}

这按预期工作。我有几个打印功能,可以检查加载的数据看起来是否正确。

现在,在正常情况下,当UICollectionView在cellForItemAt中调用此数据时,它可以正常工作。但是,在“分解方案”(如上定义)中,数据与数据源数组变量中的数据不同步。这是一个数据示例,该数据在装入时以及在细分情况下被cellForItemAt调用时的样子:

加载时检查的数据

Item(0: 1825 - No Category - indexPath = [0, 0] -      absoluteindexpath = 0
Item(1: 3630 - Filed - indexPath = [1, 0] -   absoluteindexpath = 3
Item(2: 8946 - No Category - indexPath = [0, 1] -   absoluteindexpath = 1
Item(3: 696 - No Category - indexPath = [0, 2] -   absoluteindexpath = 2

在cellForItemAt处检查的数据:     cellForItemAt正在处理图片:1825-无类别,indexPath为[0,0],absoluteindexpath为0     cellForItemAt正在处理图片:3630-已归档,indexPath为[0,1],absoluteindexpath为1     cellForItemAt正在处理图片:8946-无类别,indexPath为[0,2],absoluteindexpath为2     cellForItemAt正在处理图片:3630-已归档,indexPath为[1,0],absoluteindexpath为3

这是cellForItemAt的代码:

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

    cell.backgroundColor = UIColor.white
    cell.imageView.layer.borderColor = UIColor.black.cgColor
    cell.imageView.layer.borderWidth = 1

    // create a temporary picture object used to populate the view


    if let picture = dataSource.pictureForItemAtIndexPath(indexPath) {
        print("cellForItemAt is processing picture: \(picture.pictureName) - \(picture.pictureCategory), with indexPath of \(indexPath) and absoluteindexpath of \(dataSource.absoluteIndexForIndexPath(indexPath))")
        if debuggingMode == true {
            cell.photoIDLabel.isHidden = false
            cell.photoIDLabel.text = picture.pictureName
        }

        cell.imageView.image = getSavedImage(named: picture.pictureName)
        cell.isEditing = isEditing

    } else {
        print("did not find an image for indexpath: \(indexPath)")
    }

    return cell
}

我使用UICollectionViewController,它很大程度上依赖于RW教程中的dataSource.swift。我复制了下面的所有数据源代码,因为函数调用之间存在很多相互依赖关系。

class DataSource {
private var pictures = [Picture]()
//private var immutablePictures = [Picture]()
private var sections : [String] = []

private var latestPictureID = 0

var count: Int {
    return pictures.count
}

var numberOfSections: Int {
    return sections.count
}

// MARK:- Public
init() {
    // add init code if needed
    pictures = loadPicturesFromDisk()
}

func newPicture(newPicture: Picture) -> IndexPath {

    for picture in pictures {
        if picture.pictureName == newPicture.pictureName {
            let randomName = Int.random(in: 0 ..< 10000)
            newPicture.pictureName = String(randomName)
        }
    }
    pictures.append(newPicture)
    print("The pictureName of the saved picture = \(newPicture.pictureName)")
    saveToFile(pictures: pictures)
    print("Launching array enumeration from newPicture before sort")
    enumerateThroughPictures(pictures: pictures)
    pictures.sort { $0.pictureCategory < $1.pictureCategory }
    print("Launching array enumeration from newPicture after sort sort")
    enumerateThroughPictures(pictures: pictures)
    return indexPathForPicture(newPicture)

}

func replacePictureAtIndexPath(picture: Picture, indexPath: IndexPath) {

    // make this update the collectionview and maybe it works

    pictures[absoluteIndexForIndexPath(indexPath)] = picture
    let pictureCategory = picture.pictureCategory

    if !sections.contains(pictureCategory) {
        sections.append(pictureCategory)
    }
    saveToFile(pictures: pictures)
    print("Launching array enumeration from replacePictureAtIndexPath")
    enumerateThroughPictures(pictures: pictures)
    //pictures.sort { $0.pictureCategory < $1.pictureCategory }
}

func enumerateThroughPictures(pictures: [Picture]) {
    print("Enumerating through pictures.array:")
    var index = 0
    for picture in pictures {
        print("Item(\(index): \(picture.pictureName) - \(picture.pictureCategory) - indexPath = \(indexPathForPicture(picture)) - absoluteindexpath = \(absoluteIndexForIndexPath(indexPathForPicture(picture)))")
        index += 1
    }
}

func deleteItemsAtIndexPaths(_ indexPaths: [IndexPath]) {
    var indexes = [Int]()
    for indexPath in indexPaths {
        indexes.append(absoluteIndexForIndexPath(indexPath))
    }
    var newPictures = [Picture]()
    for (index, picture) in pictures.enumerated() {
        if !indexes.contains(index) {
            newPictures.append(picture)
        }
    }
    pictures = newPictures
}

func movePictureAtIndexPath(_ indexPath: IndexPath, toIndexPath newIndexPath: IndexPath) {
    if indexPath == newIndexPath {
        print("Returning from movePicture as indexPath and newIndexPath were the same")
        return
    }
    let index = absoluteIndexForIndexPath(indexPath)
    let currentPicture = pictures[index]
    currentPicture.pictureCategory = sections[newIndexPath.section]
    let newIndex = absoluteIndexForIndexPath(newIndexPath)
    print("About to remove picture at : \(index)")

    pictures.remove(at: index)
    print("About to add picture at : \(newIndex)")
    pictures.insert(currentPicture, at: newIndex)
}

func indexPathForPicture(_ picture: Picture) -> IndexPath {
    let section = sections.index(of: picture.pictureCategory)!
    var item = 0
    for (index, currentPicture) in picturesForSection(section).enumerated() {
        if currentPicture === picture {
            item = index
            break
        }
    }
    return IndexPath(item: item, section: section)
}

func numberOfPicturesInSection(_ index: Int) -> Int {
    let currentPictures = picturesForSection(index)
    return currentPictures.count
}

func pictureForItemAtIndexPath(_ indexPath: IndexPath) -> Picture? {
    if indexPath.section > 0 {
        let currentPictures = picturesForSection(indexPath.section)
        return currentPictures[indexPath.item]
    } else {
        return pictures[indexPath.item]
    }
}

func titleForSectionAtIndexPath(_ indexPath: IndexPath) -> String? {
    if indexPath.section < sections.count {
        return sections[indexPath.section]
    }
    return nil
}


// MARK:- Private


private func loadPicturesFromDisk() -> [Picture] {
    sections.removeAll(keepingCapacity: false)

    let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
    let archiveURL = documentsDirectory.appendingPathComponent("pictures").appendingPathExtension("plist")
    let propertyListDecoder = PropertyListDecoder()

    if let retrievedPicturesData = try? Data(contentsOf: archiveURL), let decodedPictures = try? propertyListDecoder.decode(Array<Picture>.self, from: retrievedPicturesData) {
        for picture in decodedPictures {
            let pictureName = picture.pictureName
            print("The pictureName in loadPicturesFromDisk = \(pictureName), the pictureCategory is = \(picture.pictureCategory)")
            let pictureCategory = picture.pictureCategory


            if !sections.contains(pictureCategory) {
                sections.append(pictureCategory)
            }

            let newPicture = Picture(picture: pictureName, category: pictureCategory)
            pictures.append(newPicture)

        }

        print("Enumerating through pictures in loadPicturesFromDisk")
        enumerateThroughPictures(pictures: pictures)


        return pictures

    } else {
        return []
    }
}

private func saveToFile(pictures: [Picture]) {
    let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
    let archiveURL = documentsDirectory.appendingPathComponent("pictures").appendingPathExtension("plist")
    let propertyListEncoder = PropertyListEncoder()
    let encodedPictures = try? propertyListEncoder.encode(pictures)

    try? encodedPictures?.write(to: archiveURL, options: .noFileProtection)

}

func absoluteIndexForIndexPath(_ indexPath: IndexPath) -> Int {
    var index = 0
    for i in 0..<indexPath.section {
        index += numberOfPicturesInSection(i)
    }
    index += indexPath.item
    return index
}

private func picturesForSection(_ index: Int) -> [Picture] {
    let section = sections[index]
    let picturesInSection = pictures.filter { (picture: Picture) -> Bool in
        return picture.pictureCategory == section
    }
    return picturesInSection
}

}

0 个答案:

没有答案