Как сохранить изображение из ImageView в Core Data - Swift [duplicate]

Вы можете попробовать этот код. Я нашел его раньше, когда у меня возникла проблема, похожая на вашу.

if (isset($_GET['q1mrks']) && isset($_GET['marks']) && isset($_GET['qt1'])) {
$Q1mrks = $_GET['q1mrks'];
$marks = $_GET['marks'];
$qt1 = $_GET['qt1'];

$qtype_qry = mysql_query("
    SELECT *
    FROM s_questiontypes
    WHERE quetype_id = '$qt1'
");
$row = mysql_fetch_assoc($qtype_qry);
$qcode = $row['quetype_code'];

$sq_qry = "
    SELECT *
    FROM s_question
    WHERE quetype_code = '$qcode'
    ORDER BY RAND() LIMIT $Q1mrks
";
$sq_qry = mysql_query("
    SELECT *
    FROM s_question
    WHERE quetype_code = '$qcode'
    LIMIT $Q1mrks
");
while ($qrow = mysql_fetch_array($sq_qry)) {
    $qm = $qrow['marks'] . "<br />";
    $total += $qm . "<br />";
}
echo $total . "/" . $marks;
}
24
задан R Menke 3 November 2015 в 19:50
поделиться

2 ответа

Перейти к обработке изображения, чтобы узнать, как преобразовать UIImage в NSData (что использует Core Data)

Или загрузить с github

Настройка основных данных:

Настройте два объекта: полное разрешение и миниатюру. Полные разрешения - сохранить исходное изображение. Миниатюра для хранения меньшей версии, которая будет использоваться внутри приложения. Например, вы можете использовать меньшую версию в обзоре UICollectionView.

Изображения сохраняются как Binary Data в Core Data. Соответствующим типом в Foundation является NSData. Вернитесь к UIImage с помощью UIImage(data: newImageData)



Установите флажок «Разрешить внешнее хранилище» для полей «Двоичные данные». Это автоматически сохранит изображения в файловой системе, которые ссылаются на них в Core Data

Подключите два объекта, создав отношения «один к одному» между два.

Перейти к редактору en выберите Create 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, 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, чтобы он соответствовал 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(picker: 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)

        }
    }
}

Эта функция выполняет фактическое сохранение.

  • Перейдите в поток CoreData с помощью dispatch_barrier_sync(saveQueue)
  • Сначала вставьте новый FullRes и новый объект Thumbnail в Контекст управляемого объекта.
  • Задайте значения
  • Установите связь между FullRes и Thumbnail
  • Используйте do try catch для попытки сохранения
  • Обновите управляемый объект Context, чтобы освободить память

Используя 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
    }

}
73
ответ дан R Menke 25 August 2018 в 22:15
поделиться

Основные данные не предназначены для сохранения больших двоичных файлов, таких как изображения. Вместо этого используйте Document Directory в файловой системе.

Вот пример кода для этого.

let documentsDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask, true).first as! String
 // self.fileName is whatever the filename that you need to append to base directory here.

let path = documentsDirectory.stringByAppendingPathComponent(self.fileName)

let success = data.writeToFile(path, atomically: true)
if !success { // handle error }
0
ответ дан bummi 25 August 2018 в 22:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: