2015-01-17 21 views
23

Fotoğraf kitaplığından bir görüntü seçebiliyorum ve görüntüleyebiliyorum, ancak hedefim bu seçilen görüntü veya dosya yolunu temel verilere kaydedebilmek, böylece kaydedilen kayıt bu görüntü seçildiğinde ayrıca gösterecektir.Seçilmiş Görüntüyü CoreData'ya Kaydetme

CoreData çalışmam var ve CoreData'dan metin görüntüleyebiliyorum, yalnızca görüntü beni tutuyor.

@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) 

cevap

67

(Çekirdek Veri kullandığı budur) UIImageNSData için

dönüştürmek Veya github

Çekirdek Veri Setup indirmek için öğrenmek için Resim İşleme atla:

İki varlıkları ayarlayın: Tam Çözünürlük ve Küçük Resim. Tam Çözünürlükler, orijinal resmi saklamaktır. Uygulama içinde kullanılacak daha küçük bir sürümü saklamak için küçük resim. Örneğin, daha küçük bir sürümü UICollectionView genel bakışında kullanabilirsiniz.

Görüntüler, Core Data'da Binary Data olarak depolanır. Foundation'da karşılık gelen tür NSData'dur. İkili Veri alanları için Harici Depolama kutusunu verir edin UIImage(data: newImageData)

enter image description here


enter image description here


ile UIImage geri dönüştürün. Bu, otomatik olarak ikisi arasında bire bir ilişki oluştururken, iki tarafını bağlayın

enter image description here

Çekirdek Veri bunlara başvuruda tr dosya sisteminde görüntüleri kaydeder.

enter image description here

Git Editör tr için NSManagedObjectSubclass oluştur seçeneğini belirleyin. Bu, Yönetilen Nesne Alt Sınıflarını temsil eden Sınıflar içeren dosyalar oluşturur. Bunlar proje dosya yapınızda görünecektir.

enter image description here


Temel ViewController Kurulumu:

İthalat aşağıdadır:

import UIKit 
import CoreData 

  • Kurulum iki UIButtons ve
  • iki sevk sıraları, UIImage dönüşümleri

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

Bu fonksiyon için CoreData diğeri oluşturma Interface Builder bir UIImageView doğru iş parçacığı üzerinde managedContext bir değer ayarlar . CoreData'nın aynı iş parçasında olmasını sağlamak için tüm işlemlerin bir NSManagedObjectContext olması gerektiğinden.

extension ViewController { 
    func coreDataSetup() { 
     dispatch_sync(saveQueue) { 
      self.managedContext = AppDelegate().managedObjectContext 
     } 
    } 
} 

UIViewController yüzden UIImagePickerControllerDelegate ve UINavigationControllerDelegate için bu UIImagePickerController için gerekli olan uygun uzatın.

bir kurulum fonksiyonunu oluşturma ve ayrıca başka uygulama dondurmak için görünür, temsilci fonksiyonunu hemen 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 görevden oluşturun.

Çağrı imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) içinde bu işlevi:


Resmi işleniyor.

  • İlk timeIntervalSince1970 ile geçerli tarih olsun. Bu, saniye olarak bir NSTimerInterval döndürür. Bu güzel bir Double dönüştürür. Görüntüler için benzersiz bir kimlik ve bunları sıralamanın bir yolu olarak hizmet edecektir.

  • Şimdi sıraya geçmek ve ana kuyruğu boşaltmak için iyi bir zaman. Önce ağır bir kaldırma işlemini yapmak için dispatch_async(convertQueue)'u kullandım.

  • O zaman UIImage değerini NSData'a dönüştürmeniz gerekir, bu UIImageJPEGRepresentation(image, 1) ile yapılır. 1, 1 en yüksek ve 0 en düşük olan kaliteyi temsil eder. İsteğe bağlı bir bağlayıcı kullanmam için isteğe bağlı olarak döndürür.

  • Resmi istenen bir küçültülmüş boyuta göre ölçeklendirin ve ayrıca NSData ürününe dönüştürün.

Kodu:

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) 

     } 
    } 
} 

Bu fonksiyon gerçek tasarrufu yapar.

  • İlk Yönetilen Nesne Bağlamında yeni bir FullRes ve yeni hali nesnesi eklemek dispatch_barrier_sync(saveQueue)
  • ile CoreData iplik gidin.
  • Set değerleri
  • bir biz eminiz dispatch_barrier_sync(saveQueue) kullanarak belleği

boşaltmak için

  • Yönetilen Nesne Bağlam Yenile kurtarmak girişimi FullRes ve Küçük Resmi
  • Kullanım do try catch arasındaki ilişkiyi ayarlayın Yeni bir görüntüyü güvenli bir şekilde saklayabiliriz ve bu yeni kayıtlar veya yüklemeler bitene kadar bekler.

    Kodu:

    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() 
         } 
        } 
    } 
    

    bir görüntü yüklemek için:

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

    görüntüyü büyütmek için kullanılan fonksiyonlar:

    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 
        } 
    
    } 
    
  • +0

    Teşekkürler Büyük adam çalıştı. Ayrıca, onu görüntüleyebilmem için UIImage'a geri dönüştürmeme yardımcı olabilir misiniz? – turtle02

    +0

    "Ayrıca küçük resimler oluşturup bunları ilgili bir varlıkta saklıyorum." Bir küçük resmi, küçük resme ve büyük res imgesine ilişkili bir varlığa mı kaydettiniz? Böylece ana varlık dediğinizde, büyük res imge henüz çağrılmıyor mu? – Dustin

    +0

    Aslında önemli değil. Onlar birbirleriyle ilişkilidir. Ama bu doğru. Genellikle bir uygulama ile birlikte gelen tüm verilerle uygulama kullanımı için bir varlığa sahibim. Albüm başlığı, konumu, zamanı, küçük resmi, .... Ve ihracat için tam çözünürlük içeren başka bir. Bu, filtre uygularsanız da kullanışlıdır. Kullanıcı dışa aktarılmadığında tam çözünürlüklü görüntülere filtre uygulamanıza gerek yoktur. Sadece ayarlarla oynayabilir. –

    0

    Çekirdek Verileri, görüntüler gibi büyük ikili dosyaları kurtarmak anlamına gelmez. Bunun yerine dosya sisteminde Belge Dizini kullanın.

    Bunu başarmak için örnek kod.

    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 } 
    
    +8

    İkili Veri alanlarındaki "Harici Depolamaya İzin Ver" seçeneğinin seçilmesi bu değil midir? – justColbs