问题
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