我有CoreData工作,我可以显示CoreData的文字,只是保持我的形象。
@IBAction func addPic(sender: AnyObject) { pickerController.delegate = self pickerController.sourceType = UIImagePickerControllerSourceType.PhotoLibrary // 2 self.presentViewController(pickerController,animated: true,completion: nil) // Displays image func imagePickerController(picker: UIImagePickerController!,didFinishPickingMediaWithInfo info: NSDictionary!){ image.image = info[UIImagePickerControllerOriginalImage] as? UIImage self.dismissViewControllerAnimated(true,completion: nil)
或从github下载
核心数据设置:
设置两个实体:
全分辨率和缩略图。
完整解决方案是存储原始图像。
缩略图存储应用程序中使用的较小版本。
例如,您可以在UICollectionView概述中使用较小的版本。
图像作为二进制数据存储在Core Data中。 Foundation中的相应类型是NSData。用UIImage转换回UIImage(data:newImageData)
检查允许外部存储框中的二进制数据字段。这将自动将文件系统中的图像保存在Core Data中
连接两个实体,创建两者之间的一对一关系。
转到编辑器en选择创建NSManagedObjectSubclass。
这将生成带有代表您的托管对象子类的类的文件。这些将出现在您的项目文件结构中。
基本ViewController设置:
导入以下内容:
import UIKit import CoreData
>在界面构建器中设置两个UIButtons和一个UIImageView
>创建两个调度队列,一个用于CoreData,另一个用于UIImage转换
class ViewController: UIViewController { // imageview to display loaded image @IBOutlet weak var imageView: UIImageView! // image picker for capture / load let imagePicker = UIImagePickerController() // dispatch queues let convertQueue = dispatch_queue_create("convertQueue",DISPATCH_QUEUE_CONCURRENT) let saveQueue = dispatch_queue_create("saveQueue",DISPATCH_QUEUE_CONCURRENT) // moc var managedContext : NSManagedObjectContext? override func viewDidLoad() { super.viewDidLoad() imagePickerSetup() // image picker delegate and settings coreDataSetup() // set value of moc on the right thread } // this function displays the imagePicker @IBAction func capture(sender: AnyObject) { // button action presentViewController(imagePicker,completion: nil) } @IBAction func load(sender: AnyObject) { // button action loadImages { (images) -> Void in if let thumbnailData = images?.last?.thumbnail?.imageData { let image = UIImage(data: thumbnailData) self.imageView.image = image } } } }
该函数在正确的线程上为managedContext设置一个值。由于CoreData需要一个NSManagedObjectContext中的所有操作发生在同一个线程中。
extension ViewController { func coreDataSetup() { dispatch_sync(saveQueue) { self.managedContext = AppDelegate().managedObjectContext } } }
扩展UIViewController,使其符合UIImagePickerControllerDelegate和UINavigationControllerDelegate
这些是UIImagePickerController需要的。
创建一个设置函数并创建委托函数imagePickerController(picker:UIImagePickerController,didFinishPickingImage image:UIImage,editingInfo:[String:AnyObject]?)
extension ViewController : UIImagePickerControllerDelegate,UINavigationControllerDelegate { func imagePickerSetup() { imagePicker.delegate = self imagePicker.sourceType = UIImagePickerControllerSourceType.Camera } // When an image is "picked" it will return through this function func imagePickerController(picker: UIImagePickerController,didFinishPickingImage image: UIImage,editingInfo: [String : AnyObject]?) { self.dismissViewControllerAnimated(true,completion: nil) prepareImageForSaving(image) } }
立即关闭UIImagePickerController,否则应用程序将会冻结。
处理图像:
在imagePickerController中调用此函数(选择器:UIImagePickerController,didFinishPickingImage image:UIImage,editingInfo:[String:AnyObject]?)。
>首先用timeIntervalSince1970获取当前日期。这将在几秒钟内返回一个NSTimerInterval。这很好地转换成Double。它将作为图像的唯一标识,并作为排序方式。
>现在是转移到单独的队列并释放主队列的好时机。我首先使用dispatch_async(convertQueue)在单独的线程上进行重型升级。
>然后你需要将UIImage转换为NSData这是用UIImageJPEGRepresentation(image,1)完成的。 1表示1是最高的,0是最低的质量。它返回一个可选的,所以我使用可选绑定。
>将图像缩放到所需的缩略图大小,并转换为NSData。
码:
extension ViewController { func prepareImageForSaving(image:UIImage) { // use date as unique id let date : Double = NSDate().timeIntervalSince1970 // dispatch with gcd. dispatch_async(convertQueue) { // create NSData from UIImage guard let imageData = UIImageJPEGRepresentation(image,1) else { // handle Failed conversion print("jpg error") return } // scale image,I chose the size of the VC because it is easy let thumbnail = image.scale(toSize: self.view.frame.size) guard let thumbnailData = UIImageJPEGRepresentation(thumbnail,0.7) else { // handle Failed conversion print("jpg error") return } // send to save function self.saveImage(imageData,thumbnailData: thumbnailData,date: date) } } }
此功能实际保存。
>使用dispatch_barrier_sync(saveQueue)转到CoreData线程
>首先插入一个新的FullRes和一个新的Thumbnail对象
管理对象上下文
>设置值
>设置FullRes和Thumbnail之间的关系
>使用do try catch尝试保存
>刷新受管对象上下文以释放内存
通过使用dispatch_barrier_sync(saveQueue),我们确保我们可以安全地存储一个新的映像,并且新的保存或加载将等到此完成。
码:
extension ViewController { func saveImage(imageData:NSData,thumbnailData:NSData,date: Double) { dispatch_barrier_sync(saveQueue) { // create new objects in moc guard let moc = self.managedContext else { return } guard let fullRes = NSEntityDescription.insertNewObjectForEntityForName("FullRes",inManagedObjectContext: moc) as? FullRes,let thumbnail = NSEntityDescription.insertNewObjectForEntityForName("Thumbnail",inManagedObjectContext: moc) as? Thumbnail else { // handle Failed new object in moc print("moc error") return } //set image data of fullres fullRes.imageData = imageData //set image data of thumbnail thumbnail.imageData = thumbnailData thumbnail.id = date as NSNumber thumbnail.fullRes = fullRes // save the new objects do { try moc.save() } catch { fatalError("Failure to save context: \(error)") } // clear the moc moc.refreshAllObjects() } } }
加载图像:
extension ViewController { func loadImages(fetched:(images:[FullRes]?) -> Void) { dispatch_async(saveQueue) { guard let moc = self.managedContext else { return } let fetchRequest = NSFetchRequest(entityName: "FullRes") do { let results = try moc.executeFetchRequest(fetchRequest) let imageData = results as? [FullRes] dispatch_async(dispatch_get_main_queue()) { fetched(images: imageData) } } catch let error as NSError { print("Could not fetch \(error),\(error.userInfo)") return } } } }
用于缩放图像的功能:
extension CGSize { func resizeFill(toSize: CGSize) -> CGSize { let scale : CGFloat = (self.height / self.width) < (toSize.height / toSize.width) ? (self.height / toSize.height) : (self.width / toSize.width) return CGSize(width: (self.width / scale),height: (self.height / scale)) } } extension UIImage { func scale(toSize newSize:CGSize) -> UIImage { // make sure the new size has the correct aspect ratio let aspectFill = self.size.resizeFill(newSize) UIGraphicsBeginImageContextWithOptions(aspectFill,false,0.0); self.drawInRect(CGRectMake(0,aspectFill.width,aspectFill.height)) let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage } }