【Swift 2.0】Core Data 入門、チュートリアル【図解】
こんにちは、iPhoneアプリ開発者の中川です。
現在「Core Data」の勉強中です。
勉強も一通り区切りがついたので、サンプルコードでも書いてみるかと思い、シンプルで簡単なチュートリアルをGoogleで探していたのですが、Swiftのサンプルはあれど、Swift2.0のサンプルがなかなか見つからない。結局、英語のtutorialサイトで勉強しました。英語のサイトって抵抗ある人たくさんいるだろうから(僕もそうです)、日本語で要約することにしました。
要約したサイトはこちら。
Getting Started with Core Data Tutorial
◎このチュートリアルの内容は、
・Xcodeを使ったCoreDataでのデータの永続化。
・CoreDataにレコード追加、データの保存。
・CoreDataからデータの取り出し。
・UITableViewに取り出したデータの表示。
です。
CoreDataにデータを保存して、そのデータを取り出すシンプルな例だと思っていただければいいです。
◎ではでは、さっそくはじめましょう。
Xcodeを起動し、「create a new iPhone project」テンプレートは「Single View Application」。プロジェクトの名前は「HitList」とし、「Use Core Data」にチェックします。
「Use Core Data」にチェックを入れると、自動でAppDelegate.swiftにCoreDataに必要なコードが生成されます。
次に、「Main.storyboard」をクリックして、メニューバーから「Editor → Embed in → Navigation Controller」。
「Interface Builder」に戻って、右下の「object library」から「Table View」を「ViewController」の上に配置します。
次に、「Bar Button Item」を「navigation bar」の右に配置し、ダブルクリックして名前を「Add」に変更します。
「Add」ボタンを押すとテキストフィールドが乗ったアラートビューが現れるようにします。
次に「Assistant Editor」を選択して、tableviewを右クリックもしくはCtrl+左クリックでViewControllerにoutlet接続します。
名前はtableviewとします。
1 |
@IBOutlet weak var tableView: UITableView! |
今度は「bar button」にアクションを与えます。を右クリックもしくはCtrl+左クリックでViewControllerにアクション接続します。
メソッドの名前は「addName」とします。
1 2 3 |
@IBAction func addName(sender: AnyObject) { } |
次に、配列のグローバル変数を定義します。
1 2 |
//Insert below the tableView IBOutlet var names = [String]() |
viewDidLoad()の中身を次のコードに編集します。
1 2 3 4 5 6 7 |
override func viewDidLoad() { super.viewDidLoad() title = "\"The List\"" tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Cell") tableView.dataSource = self } |
UITableViewDataSourceを追記します。
1 2 |
//Add UITableViewDataSource to class declaration class ViewController: UIViewController, UITableViewDataSource { |
ここでエラーが出るのですが、それはUITableViewDataSourceに必要なメソッドが記述していないためです。そのメソッドを記述しましょう。
viewDidLoad()メソッドの次に
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// MARK: UITableViewDataSource func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return names.count } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("Cell") cell!.textLabel!.text = names[indexPath.row] return cell! } |
これでTableViewの基本的な実装は完了しました。
次に、「addName IBAction」メソッドに以下のコードを記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
//Implement the addName IBAction @IBAction func addName(sender: AnyObject) { let alert = UIAlertController(title: "New Name", message: "Add a new name", preferredStyle: .Alert) let saveAction = UIAlertAction(title: "Save", style: .Default, handler: { (action:UIAlertAction) -> Void in let textField = alert.textFields!.first self.names.append(textField!.text!) self.tableView.reloadData() }) let cancelAction = UIAlertAction(title: "Cancel", style: .Default) { (action: UIAlertAction) -> Void in } alert.addTextFieldWithConfigurationHandler { (textField: UITextField) -> Void in } alert.addAction(saveAction) alert.addAction(cancelAction) presentViewController(alert, animated: true, completion: nil) } |
これでひとまず、Addボタンを押して名前をテーブルに追加していくことができるようになりました。
しかし、これでは追加した名前が保存できるようになっていません。アプリケーションを再起動した場合、追加した名前は消えてしまいます。
そこで、CoreDataを使ってデータの永続化ができるようにしましょう。
◎Core Data を使ってデータの永続化
Core DataはデフォルトでSQLiteを使用する設定になっています。SQLiteをイメージしながらチュートリアルを進めてください。
プロジェクトを作る段階で「Use Core Data」にチェックを入れていると自動で「HitList.xcdatamodeld」というファイルが生成されています。
「HitList.xcdatamodeld」をクリックして開きます。
左下の「Add Entity」をクリックすると、Entityというエンティティが追加されます。EntityをダブルクリックしてPersonに書き直します。
Personを選択し、Attributesのところの+ボタンをクリックし、nameというカラムをString型で設定します。
ViewController.swiftに戻ってCore Dataをインポートします。
1 2 |
//Add below "import UIKit" import CoreData |
次に、NSManagedObject型の配列をグローバル変数として用意します。
1 2 |
//Change “names” to “people” and [String] to [NSManagedObject] var people = [NSManagedObject]() |
そして、UITableViewDataSourceのメソッドを以下のように変更します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
//Replace both UITableViewDataSource methods func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return people.count } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("Cell") let person = people[indexPath.row] cell!.textLabel!.text = person.valueForKey("name") as? String return cell! } |
ここで注目していただきたいのが、NSManagedObjectの場合はDictionary型のようにキー値で取り出します。
1 |
cell!.textLabel!.text = person.valueForKey("name") as? String |
次に、addName @IBActionの中身を編集します。
1 2 3 4 5 6 7 8 |
let saveAction = UIAlertAction(title: "Save", style: .Default, handler: { (action:UIAlertAction) -> Void in let textField = alert.textFields!.first self.saveName(textField!.text!) self.tableView.reloadData() }) |
ここでエラーが出ます。というのも新たなsavenameというメソッドが呼ばれているからです。savenameメソッドを定義しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
func saveName(name: String) { //1 let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate let managedContext = appDelegate.managedObjectContext //2 let entity = NSEntityDescription.entityForName("Person", inManagedObjectContext:managedContext) let person = NSManagedObject(entity: entity!, insertIntoManagedObjectContext: managedContext) //3 person.setValue(name, forKey: "name") //4 do { try managedContext.save() people.append(person) } catch let error as NSError { print("Could not save \(error), \(error.userInfo)") } } |
1.CoreDataを使用する際は必ずNSManagedObjectContextクラスのインスタンスが必要となります。このNSManagedObjectContextインスタンスを生成する作業だと思ってください。
2.ここでは、使用するエンティティを指定したインスタンスを生成し、NSManagedObjectContext、NSEntityDescriptionを使って、NSManagedObjectインスタンスを生成します。
3.personエンティティ(テーブル)のnameカラムに値をセットする。
4.do blockを使ってデータの永続化をします。(Swift2.0からルールがこうなったようです。)
これでCoreDataにデータを保存することができました。
しかし、Runしてテーブルビューに名前を追加しても再起動するとテーブルから名前が消えてしまいます。
再起動するとテーブルが空になってしっています。
これは、データをCoreDataから読み込んでないからです。
◎データをCoreDataから取り出して読み込もう
データを取り出すためにはフェッチという作業が必要になります。
以下のメソッドをViewController.swiftに追記してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) //1 let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate let managedContext = appDelegate.managedObjectContext //2 let fetchRequest = NSFetchRequest(entityName: "Person") //3 do { let results = try managedContext.executeFetchRequest(fetchRequest) people = results as! [NSManagedObject] } catch let error as NSError { print("Could not fetch \(error), \(error.userInfo)") } } |
1.データの保存時と同じようにNSManagedObjectContextのインスタンスを生成します。
2.CoreDataからデータを取り出す場合は、NSFetchRequestクラスを使用します。
3.doブロックの中にNSManagedObjectContextとNSFetchRequestそれぞれのインスタンスを使ってフェッチを実行し、NSManagedObjectの配列peopleに適用させます。
これで再起動すると、データがテーブルに反映されるようになります。
お疲れ様です。以上でチュートリアルは終わりです。
このくらいのデータの永続化ではNSUserDefaultsを使うのが適切だと思いますが、CoreDataの練習の教材としては非常にシンプルかつ簡単で適していると思います。イメージもつきやすいのではないでしょうか。
さてさて、今回は保存、読み込みを練習しました。あとは更新だったり、データの削除、リレーションなどなど多機能なCoreDataを使う練習をしてください。
本記事を読んでいただきありがとうございました。
僕もまだCoreDataの勉強を始めたばかりです。ともにCoreDataを攻略しましょうね♪
ディスカッション
コメント一覧
まだ、コメントがありません