[iOS]Core Dataでデータベースプログラミング

[English]

 

iOSではCore DataというO/Rマッピングツールを使用してSqliteにデータを保存します。

 

環境: Xcode 8.3, Swift 3

 

1.準備

まずプロジェクト作成時に「Use Core Data」にチェックを入れます。

これによりAppDelegateにCore Dataのオブジェクトが生成されます。

 

次に[プロジェクト名.xcdatamodeld]でDBのテーブルレイアウトを定義します。

 

テーブルにImageを保存したい場合は、データ型を「Binary Data」とし、「Allows External Storage」にチェックを入れます。

Allows External Storageを指定すると、大きなサイズのImageの場合は、ImageのURLが保存される様になります。

これを指定せずにCore Dateで大きさなサイズのImageを保存すると、保存に時間がかかったり、悪い時にはメモリ使用量が一気に増えてアプリケーションがクラッシュする時があります。

 

テーブルレイアウトの定義が完了したら、XCodeの[Editor]-[Create NSManagedObject Subclass]を実行します。

この操作で定義したテーブルのクラス(NSManagedObject)が生成されます。

 

これにて準備は完了です。

あとはCore Dataを使用するクラスの先頭で「import Core Data」を宣言します。

 

2.データの新規追加(INSERT)

まずAppDelegateのNSManagedObjectContextを生成します。

次にNSMangedObjectContextから1で生成したテーブルのNSManagedObjectを生成します。

このNSMnagedObjectに値を設定して、saveメソッドを呼び出します。

説明よりもコードを見た方が早いと思いますので、コードをどうぞ。

import UIKit

import CoreData

 

class ViewController: UIViewController {  

 

 private var imageView:Array<UIImageView!> = Array<UIImageView!>() 

 

 func saveImageData(){

  

  //UIImageViewの画像をSqliteに保存   

  let imageData:NSData! = UIImageJPEGRepresentation(imageView[0].image,1.0)!

  

  var imageOrientation:Int = 0   

  if (imageView[0].image.imageOrientation == UIImageOrientation.Down){    

   imageOrientation = 2   

  }else{    

   imageOrientation = 1   

  }   

 

  let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate   

  let managedContext: NSManagedObjectContext = appDelegate.managedObjectContext   

  let objectEntity:NSManagedObject = NSEntityDescription.insertNewObjectForEntityForName("Object", inManagedObjectContext: managedContext) as NSManagedObject

  

  objectEntity.setValue(imageData, forKey: "dataValue")   

  objectEntity.setValue(imageOrientation, forKey: "imageOrientation")   

 

  do {    

   try managedContext.save()   

  }catch let error{    

   NSLog("\(error)")   

  }   

  managedContext.reset()  

 }

}

 

2.データの検索(SELECT)

次にデータを検索する場合のコードです。

func LoadData(id:String){

 var minX:CGFloat = 0

 var minY:CGFloat = 0

 var widthValue:CGFloat = 0

 var heightValue:CGFloat = 0

 var imageOrientation:Int = 0

  

 let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate   

 let managedContext: NSManagedObjectContext = appDelegate.managedObjectContext

  

 let fetchRequest = NSFetchRequest(entityName: "Object")   

 fetchRequest.returnsObjectsAsFaults = false   

 

 let predicate = NSPredicate(format: "id == %@", id)   

 fetchRequest.predicate = predicate   

 

 let descriptor_1 = NSSortDescriptor(key: "objectType", ascending: true)   

 let descriptor_2 = NSSortDescriptor(key: "createDateTime", ascending: false)   

 fetchRequest.sortDescriptors = [descriptor_1,descriptor_2]

 

 do {     

  let fetchResults: Array = try managedContext.executeFetchRequest(fetchRequest)      

 

  for fetchResult in fetchResults {       

   let object = fetchResult as! NSManagedObject

      

   width = fetchResult.valueForKey("width") as! CGFloat       

   height = fetchResult.valueForKey("height") as! CGFloat       

   minX = fetchResult.valueForKey("minX") as! CGFloat       

   minY = fetchResult.valueForKey("minY") as! CGFloat       

   data = fetchResult.valueForKey("data") as! NSData

      

   image = UIImage(data: data)       

   imageOrientation = fetchResult.valueForKey("imageOrientation") as! Int       

   if (imageOrientation == 2) {         

    image = UIImage(CGImage: image!.CGImage!, scale: image!.scale, orientation: UIImageOrientation.Down)       

   }

 

   imageView.append(UIImageView())             

   imageView[imageView.count - 1].frame = CGRect(x:minX,y:minY,width:widthValue,height:heightValue)       

   imageView[imageView.count - 1].image = image       

   self.view.addSubView(imageView[imageView.count-1])      

  }   

 }catch let error{       

  NSLog("\(error)")   

 }   

 managedContext.reset()  

}

検索条件を指定する時はNSPredicateを使用します。

ソート条件を指定する時はNSSortDescriptorを使用します。

(昇順の場合はascendingをtrueにし、降順の場合はascendingをfalseにします。)

 

尚、imageをロードした時、保存時にimageの向きが下向きであれば、imageの上下を反転しておきます。

 

3.データの上書き(UPDATE)

データを上書きする時は、対象のデータを一度検索して、その値を新しい値に上書きます。

コードは以下の様になります。

func UpdateData(id:String, objectType:Int){

    var index:Int = 0

  

 let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate   

 let managedContext: NSManagedObjectContext = appDelegate.managedObjectContext   

 

 let fetchRequest = NSFetchRequest(entityName: "Object")   

 fetchRequest.returnsObjectsAsFaults = false   

 

 let predicate = NSPredicate(format: "id == %@ And objectType == %d", id, objectType)   

 fetchRequest.predicate = predicate   

 

 do {    

  let fetchResults: Array = try managedContext.executeFetchRequest(fetchRequest)     

 

  for fetchResult in fetchResults {      

   let object = fetchResult as! NSManagedObject

 

   //検索した値を取得

   index = fetchResult.valueForKey("index") as! Int      

 

   //検索した値をUPDATE      

   object.setValue(imageView[index].frame.width, forKey: "width")      

   object.setValue(imageView[index].frame.height, forKey: "height")      

   object.setValue(imageView[index].frame.minX, forKey: "minX")      

   object.setValue(imageView[index].frame.minY, forKey: "minY")      

 

   let imageData:NSData! = UIImageJPEGRepresentation(imageView[index].image,1.0)!      

   object.setValue(imgeData, forKey: "data")

 

   var imageOrientation:Int = 0   

   if (imageView[index].image.imageOrientation == UIImageOrientation.Down){    

    imageOrientation = 2   

   }else{    

    imageOrientation = 1   

   }

   object.setValue(imageOrientation, forKey:"imageOrientation")  

  }     

  try managedContext.save()   

 }catch let error{    

  NSLog("\(error)")   

 }  

 managedContext.reset()  

}

 

4.データの削除(DELETE)

削除を行う場合も、まず一度削除対象のデータを検索してから、そのデータに削除のマークをつける手順で行います。

func DeleteData(id:String,objectType:Int){   

 let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate   

 let managedContext: NSManagedObjectContext! = appDelegate.managedObjectContext

  

 let fetchRequest = NSFetchRequest(entityName: "Object")   

 fetchRequest.returnsObjectsAsFaults = false   

 

 let predicate = NSPredicate(format: "id == %@ and objectNo == %d", id,objectType)   

 fetchRequest.predicate = predicate  

 

 do {   

  var fetchResults: Array! = try managedContext.executeFetchRequest(fetchRequest)   

  for fetchResult in fetchResults {    

   let object = fetchResult as! NSManagedObject    

 

   //削除のマークをつける    

   managedContext.deleteObject(object)   

  }

  //削除のマークをつけたデータを保存することで削除が実行される

  try managedContext.save()  

 }catch let error{    

  NSLog("\(error)")   

 }   

 managedContext.reset()  

}