微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

迅速 – 将选择的图像保存到CoreData

我可以从照片库中选择并显示图像,但我的目标是能够将所选择的图像或文件路径保存到核心数据,以便当选择保存的记录时,该图像也将显示

我有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)
跳到处理图像,以了解如何将UIImage转换为NSData(这是Core Data使用的)

或从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
    }

}

原文地址:https://www.jb51.cc/swift/320625.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐