Populating Collection View from Array in Document Directory

寵の児 提交于 2020-01-14 06:23:29

问题


This is a follow-up from this question. Thanks so much to @rmaddy and @LeoDabus for your help thus far!

The Good: my addImage button gets me the correct image in collectionView the first time I pick an image.

The Bad: the second time I select an image, it changes both cells to the 2nd image. By the third/fourth/etc times I try to addImage, the image is always the same across each cell no matter what image I choose (i.e. 1st try: image1, 2nd try: image 2, image 2, 3rd try: image 2, image 2, image 2).

My question: How do I make the image chosen populate the incremental cells correctly?

Here is my code:

Get the number of cells in the collectionView from count

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

    let fileManager = FileManager.default
    let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
    let dirContents = try? fileManager.contentsOfDirectory(atPath: documentsPath)
    let count = dirContents?.count
    return count!
        }

Populate the views

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! myCell
    let fileManager = FileManager.default
    let documentDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let directoryContents = try! fileManager.contentsOfDirectory(at: documentDirectory, includingPropertiesForKeys: nil)

    for imageURL in directoryContents where imageURL.pathExtension == "jpeg" {
        if let image = UIImage(contentsOfFile: imageURL.path) {
            cell.myImageView.image = image //[indexPath.row] **need "image" to be an array so can assign to indexPath.row
        } else {
            fatalError("Can't create image from file \(imageURL)")
        }
    }
    return cell
}

addMyImage button opens the imagePicker

@IBAction func addMyImage(_ sender: UIButton) {

//imagePickerController stuff
}

Save the imageURL in File Manager

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

if let imageURL = info[UIImagePickerControllerImageURL] as? URL {

    let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
    do {
        try FileManager.default.moveItem(at: imageURL.standardizedFileURL, to: documentDirectory.appendingPathComponent(imageURL.lastPathComponent))
        collectionView.reloadData()
    } catch {
        print(error)
    }
}

After lots of googling, I think the problem is I haven't assigned [indexPath.row] to an array in my cellForItemAt IndexPath, so while the documentDirectory gets updated with the URL, each new cell is not being pointed to the correct URL. Unfortunately, I'm calling a specific URL in that function

for imageURL in directoryContents where imageURL.pathExtension == "jpeg" 

so I am not sure how to assign the indexPath.row...

Would appreciate any help!


回答1:


You are iterating the directoryContents

for imageURL in directoryContents where imageURL.pathExtension == "jpeg" {
    if let image = UIImage(contentsOfFile: imageURL.path) {
        cell.myImageView.image = image //[indexPath.row] **need "image" to be an array so can assign to indexPath.row
    } else {
        fatalError("Can't create image from file \(imageURL)")
    }
}

that's why you only get the last image on all the cells.

What you should do is fetch the directory contents and store it in an array variable (e.g. directoryContentsArray = self.fetchDirectoryContents())

make a function similar to this, and call it on viewDidLoad: this will populate your array.

func fetchDirectoryContents() {
    let fileManager = FileManager.default
    let documentDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let directoryContents = try! fileManager.contentsOfDirectory(at: documentDirectory, includingPropertiesForKeys: nil)

    self.directoryContentsArray = directoryContents
    self.tableView.reloadData() 
}

Then use the array count for numberOfRows and for the datasource as well. your current design is actually bad right now since you're always calling for FileManager in all your tableView methods

Now, after adding an image successfully and saving it, you will repopulate your array (or you can actually just append it to your existing array)

EDIT: So in your cellForItem

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? myCell {
       let imageFile = self.directoryContentsArray[indexPath.item]
       if let imageURL = imageFile.path, 
          imageFile.pathExtension == "jpeg",
          let image = UIImage(contentsOfFile: imageURL) {
          cell.imageView.image = image
       } else {
          fatalError("Can't create image from file \(imageFile)")
       }
    return cell
    }
return UICollectionViewCell()
}


来源:https://stackoverflow.com/questions/48164074/populating-collection-view-from-array-in-document-directory

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!