草庐IT

swift - 将选取的图像保存到 CoreData

coder 2023-07-14 原文

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

我有 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)

最佳答案

跳至 处理图像 了解如何转换 UIImageNSData (这是核心数据使用的)

或从github下载

核心数据设置:

设置两个实体:
全分辨率和缩略图。
Full Resolutions 是存储原始图像。
用于存储要在应用程序内使用的较小版本的缩略图。
您可以在 UICollectionView 中使用较小的版本。例如概览。

图像存储为 Binary DataCore Data . Foundation中对应的类型是 NSData .转换回 UIImageUIImage(data: newImageData)




检查 允许外部存储 二进制数据字段框。这将自动将图像保存在文件系统中,并在 Core Data 中引用它们



连接两个实体,在两者之间创建一对一的关系。



转至 编辑 en 选择创建 NSManagedObjectSubclass .
这将生成带有代表您的托管对象子类的类的文件。这些将出现在您的项目文件结构中。



基本 View Controller 设置:

导入以下内容:

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, animated: true, 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所以它符合UIImagePickerControllerDelegateUINavigationControllerDelegateUIImagePickerController 需要这些.

    创 build 置函数并创建委托(delegate)函数 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(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) 内部调用这个函数.
  • 首先使用 timeIntervalSince1970 获取当前日期.这将返回 NSTimerInterval马上。这很好地转换为 Double .它将作为图像的唯一 id 并作为对它们进行排序的一种方式。
  • 现在是移动到单独队列并释放主队列的好时机。我用过 dispatch_async(convertQueue)首先在一个单独的线程上做繁重的工作。
  • 然后你需要转换UIImageNSData这是通过 UIImageJPEGRepresentation(image, 1) 完成的. 1代表品质在哪里1是最高的和0是最低的。它返回一个可选的,所以我使用了可选的绑定(bind)。
  • 将图像缩放到所需的缩略图大小并转换为 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, 0, aspectFill.width, aspectFill.height))
            let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
    
            return newImage
        }
    
    }
    

    关于swift - 将选取的图像保存到 CoreData,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27995955/

    有关swift - 将选取的图像保存到 CoreData的更多相关文章

    1. ruby-on-rails - 添加回形针新样式不影响旧上传的图像 - 2

      我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司

    2. ruby-on-rails - 在 Ruby (on Rails) 中使用 imgur API 获取图像 - 2

      我正在尝试使用Ruby2.0.0和Rails4.0.0提供的API从imgur中提取图像。我已尝试按照Ruby2.0.0文档中列出的各种方式构建http请求,但均无济于事。代码如下:require'net/http'require'net/https'defimgurheaders={"Authorization"=>"Client-ID"+my_client_id}path="/3/gallery/image/#{img_id}.json"uri=URI("https://api.imgur.com"+path)request,data=Net::HTTP::Get.new(path

    3. python ffmpeg 使用 pyav 转换 一组图像 到 视频 - 2

      2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p

    4. ruby - 是否有将图像文件转换为 ASCII 艺术的命令行程序或库? - 2

      有这样的事吗?我想在Ruby程序中使用它。 最佳答案 试试这个http://csl.sublevel3.org/jp2a/此外,Imagemagick可能还有一些东西 关于ruby-是否有将图像文件转换为ASCII艺术的命令行程序或库?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/6510445/

    5. ruby-on-rails - 使用 Dragonfly 从 URL 分配图像 - 2

      我正在使用Dragonfly在Rails3.1应用程序上处理图像。我正在努力通过url将图像分配给模型。我有一个很好的表格:{:multipart=>true}do|f|%>RemovePicture?Dragonfly的文档指出:Dragonfly提供了一个直接从url分配的访问器:@album.cover_image_url='http://some.url/file.jpg'但是当我在控制台中尝试时:=>#ruby-1.9.2-p290>picture.image_url="http://i.imgur.com/QQiMz.jpg"=>"http://i.imgur.com/QQ

    6. Ruby-vips 图像处理库。有什么好的使用示例吗? - 2

      我对图像处理完全陌生。我对JPEG内部是什么以及它是如何工作一无所知。我想知道,是否可以在某处找到执行以下简单操作的ruby​​代码:打开jpeg文件。遍历每个像素并将其颜色设置为fx绿色。将结果写入另一个文件。我对如何使用ruby​​-vips库实现这一点特别感兴趣https://github.com/ender672/ruby-vips我的目标-学习如何使用ruby​​-vips执行基本的图像处理操作(Gamma校正、亮度、色调……)任何指向比“helloworld”更复杂的工作示例的链接——比如ruby​​-vips的github页面上的链接,我们将不胜感激!如果有ruby​​-

    7. ruby-on-rails - 如何播种图像的路径? - 2

      Organization和Image具有一对一的关系。Image有一个名为filename的列,它存储文件的路径。我在Assets管道中包含这样一个文件:app/assets/other/image.jpg。播种时如何包含此文件的路径?我已经在我的种子文件中尝试过:@organization=...@organization.image.create!(filename:File.open('app/assets/other/image.jpg'))#Ialsotried:#@organization.image.create!(filename:'app/assets/other/i

    8. ruby-on-rails - 安全地显示使用回形针 gem 上传的图像 - 2

      默认情况下:回形针gem将所有附件存储在公共(public)目录中。出于安全原因,我不想将附件存储在公共(public)目录中,所以我将它们保存在应用程序根目录的uploads目录中:classPost我没有指定url选项,因为我不希望每个图像附件都有一个url。如果指定了url:那么拥有该url的任何人都可以访问该图像。这是不安全的。在user#show页面中:我想实际显示图像。如果我使用所有回形针默认设置,那么我可以这样做,因为图像将在公共(public)目录中并且图像将具有一个url:Someimage:看来,如果我将图像附件保存在公共(public)目录之外并且不指定url(同

    9. ruby - Paperclip:以编程方式分配图像并设置其名称 - 2

      使用Paperclip,我想从这样的URL抓取图像:require'open-uri'user.photo=open(url)问题是我最后得到一个像“open-uri20110915-4852-1o7k5uw”这样的文件名。有什么方法可以更改user.photo上的文件名?作为一个额外的变化,Paperclip将我的文件存储在S3上,所以如果我可以在初始分配中设置我想要的文件名就更好了,这样图像就会上传到正确的S3key。像这样:user.photo=open(url),:filename=>URI.parse(url).path 最佳答案

    10. ruby - 将哈希值保存到 Ruby 上的文件 - 2

      我刚刚迈出了编程的第一步。我刚刚完成了CodeAcademy的另一门类(class)。这次我被要求创建一个小电影目录。这是我的问题:如何在文件中保存/加载带有电影标题和评级的哈希值而不是自己的代码?下面是代码现在的样子(几句葡萄牙语,但您可以忽略它:movies={Memento:3,Primer:4,Ishtar:1}puts"Oquevocêgostariadefazer?"puts"--Digite'add'paraadicionarumfilme."puts"--Digite'update'paraatualizarumfilme."puts"--Digite'display'

    随机推荐