我正在创建照片识别应用程序,该应用程序使用核心数据来持久保存从照片库或相机加载到应用程序中的用户图像。我一直在遵循一个发现here的指南,该指南使用核心数据保存和加载图像,但是在视图控制器中显示它们时遇到了麻烦:
将图像加载到CameraViewController中的应用程序中,并在ImpagePickerController函数上调用PrepareImageforSaving方法:
class CameraViewController: SharedImagePickerController {
let session = URLSession.shared
var landmark: Landmark!
var dataController: DataController!
/// The Core Data managed context
var managedContext : NSManagedObjectContext?
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
@IBOutlet weak var landmarkResults: UITextView!
@IBOutlet weak var CameraPhoto: UIImageView!
@IBAction func chooseImage(_ sender: Any) {
let sharedImagePickerController = UIImagePickerController()
sharedImagePickerController.delegate = self
let actionSheet = UIAlertController(title: "Photo Source", message: "Choose a source", preferredStyle: .actionSheet)
actionSheet.addAction(UIAlertAction(title: "Camera", style: .default, handler: {(action:UIAlertAction) in
sharedImagePickerController.sourceType = .camera
self.present(sharedImagePickerController, animated: true, completion: nil)
}))
actionSheet.addAction(UIAlertAction(title: "Photo Library", style: .default, handler: {(action:UIAlertAction) in
sharedImagePickerController.sourceType = .photoLibrary
self.present(sharedImagePickerController, animated: true, completion: nil)
}))
actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(actionSheet, animated: true, completion: nil )
}
override func viewDidLoad() {
super.viewDidLoad()
let tapGesture = UITapGestureRecognizer(target: self, action: Selector(("imageTapped:")))
CameraPhoto.addGestureRecognizer(tapGesture)
CameraPhoto.isUserInteractionEnabled = true
activityIndicator.hidesWhenStopped = true
coreDataSetup()
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let pickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
CameraPhoto.contentMode = .scaleAspectFit
CameraPhoto.image = pickedImage
activityIndicator.startAnimating()
let binaryImageData = base64EncodeImage(pickedImage)
createRequest(with: binaryImageData)
dismiss(animated: true, completion: nil)
prepareImageForSaving(pickedImage)
}
}
func saveLandmark(givenName: String) {
let entity = NSEntityDescription.entity(forEntityName: "Landmark", in: dataController.viewContext)
let item = NSManagedObject(entity: entity!, insertInto: dataController.backgroundContext!)
item.setValue(givenName, forKey: "name")
do {
try dataController.backgroundContext!.save()
} catch {
print("Something went wrong")
}
}
然后在LandmarkListViewController中,在ViewDidLoad上调用loadImages函数:
class LandmarkListViewController: UIViewController, UITableViewDelegate {
@IBOutlet var tableView: UITableView!
var dataController: DataController!
var tableViewDataSource = TableViewDataSource()
override func viewDidLoad() {
super.viewDidLoad()
loadImages { (landmarks) -> Void in
var newLandmarks : [Landmark] = []
for landmark in landmarks {
// filter out duplicates
let isDuplicate = self.tableViewDataSource.data.contains {
return $0.id == landmark.id
}
if !isDuplicate {
newLandmarks.append(landmark)
}
}
var paths : [IndexPath] = []
let start = self.tableViewDataSource.data.count
self.tableViewDataSource.data += newLandmarks.map { return (image:$0.image ?? UIImage(),id:$0.id ?? 0.0) }
let end = self.tableViewDataSource.data.count
for i in start..<end {
paths.append(IndexPath(row: i, section: 0))
}
// make sure it updates happen on the main thread
Run.main {
self.tableView.beginUpdates()
self.tableView.insertRows(at: paths, with: UITableView.RowAnimation.fade)
self.tableView.endUpdates()
}
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let indexPath = tableView.indexPathForSelectedRow {
tableView.deselectRow(at: indexPath, animated: false)
tableView.reloadRows(at: [indexPath], with: .fade)
}
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
}
// Actions
@IBAction func closeButtonPressed(_ sender: Any) {
navigationController?.dismiss(animated: true, completion: nil)
}
}
extension LandmarkListViewController: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)
break
case .delete:
tableView.deleteRows(at: [indexPath!], with: .fade)
break
case .update:
tableView.reloadRows(at: [indexPath!], with: .fade)
case .move:
tableView.moveRow(at: indexPath!, to: newIndexPath!)
}
}
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)
case .update, .move:
fatalError("Invalid change type in controller(_:didChange:atSectionIndex:for:). Only .insert or .delete should be possible.")
}
}
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.beginUpdates()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.endUpdates()
}
}
我很想念我为什么失踪。我是Core Data和程序设计的新手,所以如果我错过了明显的事情,请不要提出任何建议。感谢您的反馈。