无法将图像加载到核心数据中的相册

trouble loading images to photo album in core data

我在核心数据中设置了一对多关系

一个相册可以保存多张图片

每次我创建新相册时,都会加载相同的图像。我希望用户能够将不同的照片保存到每个相册

我认为问题可能出在我尝试加载数据时的谓词上,但我不完全确定。很抱歉 post 使用所有这些可能不相关的代码,但我想 post 所有代码以防万一我没有看到其他人可能会捕捉到的东西。

我还想补充一点,当我添加 NSPredicate 的代码时,当我单击相册单元格时,集合视图中没有图像显示,但是当我在 loadData() 中注释掉谓词的代码时,图像显示。我不知道为什么会这样。

      class ViewController: UIViewController  {
var fetchedResultsController: NSFetchedResultsController<PhotoAlbum>!

var contextApp  = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var moc:NSManagedObjectContext! = nil

@IBOutlet weak var tableView: UITableView!


func setupFetchedResultsController() {


    let fetchRequest:NSFetchRequest<PhotoAlbum> = PhotoAlbum.fetchRequest()

    let sortDescriptor = NSSortDescriptor(key: "album", ascending: true)
    fetchRequest.sortDescriptors = [sortDescriptor]


    fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: contextApp, sectionNameKeyPath: nil, cacheName: nil)

    fetchedResultsController.delegate = self


    do {
        try fetchedResultsController.performFetch()
    }catch {
        print(error)
    }


}

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    tableView.delegate = self
    tableView.dataSource = self


    setupFetchedResultsController()
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)


    setupFetchedResultsController()


}


@IBAction func createNewAlbum(_ sender: UIBarButtonItem) {
    presentnewAlbumAlert()
}




func presentnewAlbumAlert () {
    let alert = UIAlertController(title: "New Album", message: "Enter a name for this album", preferredStyle: .alert)

    // Create actions
    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
    let saveAction = UIAlertAction(title: "Save", style: .default) { [weak self] action in
        if let name = alert.textFields?.first?.text {
            self?.addAlbumCell(name: name)
        }
    }
    saveAction.isEnabled = false

    // Add a text field
    alert.addTextField { textField in
        textField.placeholder = "Name"
        NotificationCenter.default.addObserver(forName: UITextField.textDidChangeNotification, object: textField, queue: .main) { notif in
            if let text = textField.text, !text.isEmpty {
                saveAction.isEnabled = true
            } else {
                saveAction.isEnabled = false
            }
        }
    }

    alert.addAction(cancelAction)
    alert.addAction(saveAction)
    present(alert, animated: true, completion: nil)
}


func addAlbumCell(name: String) {

    let album = PhotoAlbum(context: contextApp)
    album.album = name

    do {
        try contextApp.save()
    }catch{
        print(error)
    }

}
func deleteNote(at indexPath: IndexPath) {
    let albumToDelete = fetchedResultsController.object(at: indexPath)
    contextApp.delete(albumToDelete)
    try? contextApp.save()
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    if segue.identifier == "toCollection" {
        if let indexPath = tableView.indexPathForSelectedRow {
            let object = fetchedResultsController.object(at: indexPath)

           (segue.destination as! PhotoViewController).album = object


     }  


    }

}

} // 标记:数据源

     extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: 
Int) -> Int {
    return fetchedResultsController?.sections![section].numberOfObjects 
?? 0
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let aNewalbum = fetchedResultsController.object(at: indexPath)

    let cell = tableView.dequeueReusableCell(withIdentifier: "toCollection", for: indexPath)

    cell.textLabel?.text = aNewalbum.album



    return cell
}

}

// 标记:DELGEATE

extension ViewController : UITableViewDelegate {

func numberOfSections(in tableView: UITableView) -> Int {
    return fetchedResultsController?.sections?.count ?? 1
}

}

// SETUP NSFetchedResultsControllerDelegate

   extension ViewController : NSFetchedResultsControllerDelegate {

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
    switch type {
    case .insert:
        tableView.insertRows(at: [newIndexPath!], with: .fade)
    case .delete :
        tableView.deleteRows(at: [indexPath!], with: .fade)

    default:
        break
    }
}

 func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
    let indexSet =  IndexSet(integer: sectionIndex)
    switch type {
    case .insert:
        tableView.insertSections(indexSet, with: .fade)

    case .delete :
        tableView.deleteSections(indexSet, with: .fade)

    default:
        break
    }
}


func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    tableView.beginUpdates()
    tableView.reloadData()
}

   func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    tableView.endUpdates()
    tableView.reloadData()
  }   

}

集合视图的代码

  class PhotoViewController: UIViewController , UICollectionViewDelegate , UICollectionViewDataSource , UICollectionViewDelegateFlowLayout , UIImagePickerControllerDelegate , UINavigationControllerDelegate  {

var imageDataArray = [Images]()
var imageArray = [UIImage]()
var managedObjectContext:NSManagedObjectContext!
var mySelection:Int?
var album: PhotoAlbum!




@IBOutlet var collectionView: UICollectionView!


@IBAction func addImage(_ sender: Any) {

    let picker:UIImagePickerController = UIImagePickerController()
    picker.sourceType = .photoLibrary
    picker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!

    picker.delegate = self
    picker.allowsEditing = false
    self.present(picker, animated: true, completion: nil)

}





// Setup the collection view

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

    let imageItem = imageDataArray[indexPath.row]


    if let presentImage = UIImage(data: (imageItem.images as! Data) ){
        cell.chosenImage.image = presentImage
        mySelection = indexPath.row
        imageArray.append(presentImage)
    }

    return cell
}

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

    return imageDataArray.count
}

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

    if let pickedImage = (info[UIImagePickerController.InfoKey.originalImage] as? UIImage) {
        picker.dismiss(animated: true) {
            self.createImageContext(with: pickedImage)
            self.imageArray.append(pickedImage)

        }
    }
}

// 加载和保存图像

func loadData() {
    let imageReqeust: NSFetchRequest<Images>  = Images.fetchRequest()

    let predicate = NSPredicate(format: "images.album == %@", album)
    imageReqeust.predicate = predicate

   // print(predicate.description)
    do {
        imageDataArray = try managedObjectContext.fetch(imageReqeust)
        self.collectionView.reloadData()
    }catch {
        print("Could not load data from database \(error.localizedDescription)")
    }
}


func createImageContext( with image: UIImage) {
    let imageItem = Images(context: managedObjectContext!)
    imageItem.images = NSData(data: image.jpegData(compressionQuality: 1.0)!) as Data
    //            imageItem.image = NSData(data: UIImageJPEGRepresentation(image, 0.3)!) as Data



    do {
        try self.managedObjectContext.save()
        self.loadData()
    }catch {
        print("Could not save data \(error.localizedDescription)")
    }




}

// ViewDidLoad

override func viewDidLoad() {
    super.viewDidLoad()


    collectionView.delegate = self
    collectionView.dataSource = self

    managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

    self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addImage(_:)))

    loadData()
    // Do any additional setup after loading the view.
}

在您的第二个视图控制器中,您不需要从核心数据中获取图像,而是可以通过您的相册访问它们 属性。

imageDataArray = Array(album.images)

保存新图像实例时,不要忘记将其分配到相册

imageItem.album = self.album