CoreDataの主キー


81

これはばかげているように見えるかもしれませんが、xcdatamodelファイルで属性を主キーとしてマークする方法を理解できませんでした。私の永続ストレージはsqliteファイルです。誰か助けてもらえますか?

その場合、IDを一意に「検証」するにはどうすればよいですか?検証方法か何かを書くべきですか?

回答:


92

オプションは次のとおりです。

  • を使用し-[NSManagedObject objectID]ます。このIDは、オブジェクトが初めて保存されるか、呼び出すまで一時的なものであることに注意してください。-[NSManagedObjectContext obtainPermanentIDsForObjects:error:]
  • CFUUID関数ファミリーを使用して、-awakeFromInsertメソッド内の各オブジェクトのUUIDを生成します
  • モデルに整数を格納し、各オブジェクトの作成に伴って整数をインクリメントする、独自の主キーのようなシステムを作成します

プロパティが一意であることを検証する良い方法はありません。最も近い方法は、作成時に一意であることを確認してから、IDを変更することのないカスタムセッターメソッドを実装することです。


5
はるかに建設的な答え-あなたは解決策としてマークされるべきです!
Grouchal 2011

1
UUIDを生成するのが最善の方法です。私たちはアプリでそれを使用しており、非常にうまく機能しています。
object2.0 2013年

46

Core Dataはオブジェクトグラフの永続化フレームワークであり、データベースではないことに注意してください。主キーのようなものは、永続ストアの実装に依存するため、抽象化されます。


2
これが@Mugunthが選ぶべき答えだったはずです!あなたの洞察力をありがとう。
Leonard

では、Core Dataはそれ自体で主キーを生成するだけでしょうか?
次の開発者

24

CoreDataは独自の主キーを作成します。追加する必要はありません。あなたはそれを取得することができます

NSManagedObjectID *moID = [managedObject objectID];

14

ハッキングするときに、主キーの実際の整数が必要になることがあります。これがそれをつかむ方法です:

NSManagedObjectID *yourManagedObjectID = [yourManagedObject objectID];
int yourManagedObject_PK = [[[[[yourManagedObjectID URIRepresentation] absoluteString] lastPathComponent] substringFromIndex:1] intValue];

CoreDataはオブジェクトグラフですが、CoreDataで生成されたSQLiteデータベースデータを見ると、NSManagedObjectの主キーを取得するこの方法は問題になりません。iiは同じコードでCoreDataと低レベルのsqlite3Cライブラリを一緒に使用しており、レコードをフェッチするためにCoreDataからsqlite3に主キーを渡すことは問題なく機能します。

!このコードを本番環境で使用する場合は、dbプライマリキーがURIRepresentationに変換される方法に内部変更が加えられる可能性があることに注意してください。これにより、コードが破損する可能性があります。

楽しい


1
object-IDとSQLiteRIDの間に関係は定義されていません。特定のバージョンの一時キーにのみ使用できますが、他のバージョンではサイレントに破壊される可能性があるため、永続的な主キーのアプローチは間違っています。
eonil 2012

「他のバージョンで壊れた」とはどういう意味ですか?主キーを変更する必要があるのはなぜですか?
manitu 2012

PK値は変更されませんが、アルゴリズムが公式に定義されていないため、URL表現を作成するアルゴリズムが変更される可能性があります。その場合、コードが有効なPK値を抽出することは保証されません。(アルゴリズムを定義しているソースがある場合は、お知らせください。投稿することをお勧めします)
eonil 2012

1
OK。時々、ハッキング部分が納得できるとき。私の反対票は現在ロックインされているので、編集を加えると反対票が削除されます。
eonil 2012

2
速度と効果のために、SQLが最適な方法である場合があります。私の例では、count(*)、合計、平均、およびグループを保持するクエリです。OOで行うのは苦痛であり、SQLの場合は1行です。その「ハック」は完全に機能し、Appleがそれを変更した場合でも、何らかの方法でSQL結合を機能させる必要があるため、しばらくは問題ないと思います;)。理論的にはこれを行うべきではないとしても、投票してください。私の意見では、DBを完全に隠すことは、実際の技術的な理由よりも原則によって引き起こされるエラーです。それを行い、SQLでバッチを取得します。フレームワークが利用可能であっても、他の多くのシステムでは常に。
Eric Giguere 2014

0

NSManagedObjectIDをハッキングすることなく、リモートデータ収集を管理する前に属性の高速チェックを実行できます。

ユーティリティメソッドを作成しました。ここ確認してください


0

主キーを取得するためのSwift拡張機能

extension NSManagedObject {
    var primaryKey : String {
        guard objectID.uriRepresentation().lastPathComponent.count > 1 else { return "" }
        return objectID.uriRepresentation().lastPathComponent.substring(from: 1)
    }
}

そして文字列の場合

extension String
{
    func substring(from : Int) -> String {
        guard self.count > from else { return "" }
        return String(self[self.index(self.startIndex, offsetBy: from)...])
     }
}

-3

一意の識別子として時間+クラス名を使用したいと思います。


2
あまりお勧めしませんが、同時に複数のオブジェクトが作成されないことをいつ保証できますか?
fat32 2016年

あまりお勧めしません。この方法では、キーが一意であることを保証できません。
コーディ2016年

@Fynh私はコードを投稿しましたが、私の投稿は不完全かもしれませんが、私は常にタイムゲッターメソッドを同期しています。
infiniteLoop
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.