[Swift] CoreDataを使ってみる

公開日: : 最終更新日:2014/10/22 iPhone App 開発, Swift

SwiftでCoreData

今回はSwiftでCoreDataを使ってみます。
Xcodeプロジェクトのテンプレート[Master-Detail Application]を利用します。
言語はSwift、XCodeのバージョンは6.0です。

まずは、メニューのFile > New > Project…でテンプレート選択画面を表示します。
スクリーンショット 2014-10-10 13.40.43
Master-Detail Applicationを選択。

Product NameはMasterDetailTest、LanguageはSwift。
あとはUse Core Dataにチェックをお忘れなく。
スクリーンショット 2014-10-10 12.35.54

すると、ファイルが自動生成されます。
MasterViewControllerが最初の一覧画面。
DetailViewControllerが行選択で遷移された詳細画面になります。
試しに実行してみると、
スクリーンショット 2014-10-10 14.04.28
スクリーンショット 2014-10-10 14.04.33
+ボタンでデータが新規追加され、行選択で詳細画面に移動します。

テーブルの作成

今度はテーブルを作成してみます。
MasterDetailTest.xcdatamodeldを開いてデータを作成します。
このファイルにテーブル間のリレーション情報などを設定することも可能です。
まずはエンティティ名をSampleEntity、属性にid(Integer 32)、name(String)を設定します。
スクリーンショット 2014-10-10 13.36.02
次に、定義したSampleEntityのモデルクラスを作成します。
File > New > File…から新規ファイル画面を表示
NSManagedObject subclass を選択、エンティティの選択はSampleEntityにし、
LangageはSwiftにしてください。
スクリーンショット_2014-10-10_13_24_17
SampleEntity.swiftファイルが自動生成されました。
ソースはこちら。

import Foundation
import CoreData

class SampleEntity: NSManagedObject {

    @NSManaged var id: NSNumber?
    @NSManaged var name: String?

}

ここで各プロパティにオプショナルを設定してください。
変数の後に’?’を付加するとこでnilを許容できるようになります。
これがないと値取得時にエラーになります。
あと、Objective-Cでは@dynamicとなっていたものが、@NSManagedになっています。

ソースコードの編集

テンプレートのままではtimeStampを出力していますが、先ほど作成したテーブルを取得するように変更してみます。
処理の流れはこんな感じです。

  1. データの検索部分をSampleEntityテーブルから取得するように変更
  2. +ボタン押下で登録するときに、SampleEntityテーブルに登録するように変更(idのインクリメント)
  3. 一覧、詳細画面のデータ表示部分はSampleEntityテーブルのnameに変更

MasterViewController.swift

fetchedResultsController

画面がロードする毎にデータを取得します。コメントの部分は元のソースコードになります。

var fetchedResultsController: NSFetchedResultsController {
    if _fetchedResultsController != nil {
        return _fetchedResultsController!
    }

    let fetchRequest = NSFetchRequest()
    //let entity = NSEntityDescription.entityForName("Event", inManagedObjectContext:self.managedObjectContext!)
    let entity = NSEntityDescription.entityForName("SampleEntity", inManagedObjectContext:self.managedObjectContext!)
    fetchRequest.entity = entity

    fetchRequest.fetchBatchSize = 20

    //let sortDescriptor = NSSortDescriptor(key: "timeStamp", ascending: false)
    let sortDescriptor = NSSortDescriptor(key: "id", ascending: true)
    let sortDescriptors = [sortDescriptor]
    fetchRequest.sortDescriptors = [sortDescriptor]

    let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest,managedObjectContext: self.managedObjectContext!, sectionNameKeyPath: nil, cacheName: "Master")
    aFetchedResultsController.delegate = self
    _fetchedResultsController = aFetchedResultsController

	var error: NSError? = nil
	if !_fetchedResultsController!.performFetch(&error) {
	     abort()
	}

    return _fetchedResultsController!
}

insertNewObject

データの登録処理です。
EventテーブルのtimeStampを設定している箇所をコメントアウトし、SampleEntityのname、idを設定するようにします。
getNextId関数はidの最大値 + 1を取得する処理です。
idにそれを設定し、nameは’name’ + ‘id’にします。

func insertNewObject(sender: AnyObject) {
    let context = self.fetchedResultsController.managedObjectContext
    let entity = self.fetchedResultsController.fetchRequest.entity
    //let newManagedObject = NSEntityDescription.insertNewObjectForEntityForName(entity.name, inManagedObjectContext: context) as NSManagedObject
    //newManagedObject.setValue(NSDate.date(), forKey: "timeStamp")

    let newSampleEntity = NSEntityDescription.insertNewObjectForEntityForName("SampleEntity", inManagedObjectContext: context) as SampleEntity
    newSampleEntity.id = NSNumber(int: self.getNextId())
    newSampleEntity.name = "name" + newSampleEntity.id!.stringValue

    var error: NSError? = nil
    if !context.save(&error) {
        abort()
    }
}

func getNextId() -> Int32 {
    let context = self.fetchedResultsController.managedObjectContext
    let entity = self.fetchedResultsController.fetchRequest.entity
    let fetchRequest = NSFetchRequest()
    fetchRequest.entity = entity

    let keyPathExpression = NSExpression(forKeyPath: "id")
    let maxExpression = NSExpression(forFunction: "max:", arguments: [keyPathExpression])
    let description = NSExpressionDescription()
    description.name = "maxId"
    description.expression = maxExpression
    description.expressionResultType = .Integer32AttributeType

    fetchRequest.propertiesToFetch = [description]
    fetchRequest.resultType = .DictionaryResultType

    if let results = context.executeFetchRequest(fetchRequest, error: nil) {
        if results.count > 0 {
            let maxId = results[0]["maxId"] as Int
            return maxId + 1;
        }
    }
    return 1
}

insertNewObjectはテーブル名、取得カラムを変えるだけでOK。
getNextIdは新たにNSFetchRequestを生成し、DB問い合わせの準備をします。
集計関数を使う場合はNSExpression、NSExpressionDescriptionを使用します。
expressionResultTypeは結果のタイプでDBの形式に合わせて設定します。
30行目のpropertiesToFetchにNSExpressionDescriptionを設定し、31行目でSQL問い合わせの結果タイプを設定します。

configureCell

データを表示する関数です。

func configureCell(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath) {
    //let object = self.fetchedResultsController.objectAtIndexPath(indexPath) as NSManagedObject
    //cell.textLabel?.text = object.valueForKey("timeStamp")!.description
    let object = self.fetchedResultsController.objectAtIndexPath(indexPath) as SampleEntity
    cell.textLabel?.text = object.name
}

DetailViewController.swift

configureView

データの表示をSampleEntityテーブルのnameに変更します。

func configureView() {
    if let detail: AnyObject = self.detailItem {
        if let label = self.detailDescriptionLabel {
            label.text = detail.valueForKey("name")!.description
        }
    }
}

以上、コーディングが終わりました。
実行してみます。
iOS Simulator Screen Shot 2014.10.14 17.07.30

iOS Simulator Screen Shot 2014.10.14 17.07.36

まとめ

テーブルを作成し、登録処理を変更しただけですがオプショナルの設定にかなり手こずりました。
忘れやすいのはManagedObjectの子クラス(データ定義クラス)でnilを許容する’?’を追加することです。
また、今回は集合関数maxを用いてデータを取得してみましたが、sumやminを使っても同様に取得可能です。

ad

関連記事

[Swift] 画像を合成する

画像を合成 以下の2つの画像を合成してみます。円と四角です。 画像をプロジェクトに追

記事を読む

no image

迷走継続中!

どうも、僕です。 相変わらず迷走中な訳ですが、新たに迷走アイテムを入手しました。 その名

記事を読む

[Objective-C] デリゲート (Delegate)を理解する!

デリゲートとは? デリゲートに関しての意味合いとして、”委譲”とか”代理”と説明されることが多いで

記事を読む

no image

一旦、離脱中!

サイト制作の仕事がちょろちょろちょろっと入ってきたので、寂しいけれどしばしXcodeとはお別れ。

記事を読む

Swiftの覚書1

Swift 先日、Appleから新言語Swiftが発表されました。 今までiOSアプ

記事を読む

[iPhone App]WorkManager アップデートしました。

Processing For App Storeでやきもきした僕です。こんにちわ。 今

記事を読む

[Swift] ビルド時のエラー&iOS8でNSBigDecimalのバグ

ビルド時のエラー Swiftプロジェクトを実行中に以下のエラーが出ました。 "__TFSs15_

記事を読む

[iPhone App] WorkManagerの不具合について

バージョン1.2.2の不具合 11/25日現在、iPhoneアプリの「WorkManger」バージ

記事を読む

no image

小さなことからコツコツと

これまでHTMLとCSSだけで生きてきただけあって、プログラム言語がいまいちわからない。 Mo

記事を読む

[Swift] UITabBarControllerでタブ選択時のイベントを取得する

UITabBarController タブを使った画面を作成する場合はUITabBarContro

記事を読む

ad

Comment

  1. Ratsitobaina より:

    after spending 4hours for looking how to use nsexpression with swift in google, I found a good response at your site !!!.

    Thanks you very much.
    Ratsitobaina

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

ad

[PHP] curl転送してみる(googleに)

curlでgoogle画像検索APIにアクセスしてみます。 cu

[PHP] PDOでMySQLの接続確認をする

PDO PHPでMySQLに接続する際には、mysql_connec

[PHP] ランダムな英数字を生成する

便利系メソッド 今回はPHPでランダムな英数字を作成してみます。

[Swift] プロパティリスト(plist)の値を取得

plistからデータを取得してみます。 こちらのエントリーも参考にし

[Swift] Asset Catalogについて

XCode5から追加されたAsset Catalog。 いままで標準

→もっと見る

  • 1978年の七夕生まれ。 25才でweb業界の門を叩き、28才でフリーランスに。 現在は、フリーランスでマークアップ中心に、wordpressのカスタマイズやデザインをしております。 また、iPhoneアプリの開発もしております。
PAGE TOP ↑