web-dev-qa-db-ja.com

iPhoneでCore Dataプログラムの一意のIDを作成する

このコアデータを理解するのに少し苦労しています。一意のIDで新しいエントリを作成するにはどうすればよいですか? SQLでは、1つのフィールドを自動インクリメントフィールドとして宣言するだけです。ここではそのようなものは見ていませんが、何かが足りない可能性があります。 NSIntegerフィールドの自動インクリメントが必要なため、データベースにアイテムを手動で追加するときに、何らかの形式の参照があります。

57
user165411

あなたの言ったことには同意しますが、コアデータの背後にはIDメカニズムがあります。 IDは確かにCore-Dataによって管理されますが、次の方法で取得できます。

NSManagedObjectID *moID = [managedObject objectID];

詳細については、以下を参照してください。 Core Data Programming Guide

146
user142764

それはCoreDataの仕組みではありません。

CoreDataでは、エンティティのインスタンスを作成します。各インスタンスは一意です。その後、必要に応じてインスタンスを取得および操作します。 CoreDataは、インスタンスを一意に識別するなど、永続性を管理します。

従来のリレーショナルデータベースについて知っているすべてのことから離れてください。

CoreDataは、永続性のようなデータベースをはるかに超える機能を提供する、非常に強力なテクノロジです。多くのコード行を節約し、それを採用すれば非常にうまく機能します。

28
bbum

このクラス関数は、idプロパティに対して次に利用可能な数を返します(整数プロパティである必要があります)。

自動増分値ジェネレーターと呼びます。私はまだそのためのobjectIDがあることに他の人に同意しますが、時々あなただけの番号が必要です。

この関数は、エンティティのNSManagedObjectサブクラスに配置できます。

+(NSNumber *)nextAvailble:(NSString *)idKey forEntityName:(NSString *)entityName inContext:(NSManagedObjectContext *)context{


    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSManagedObjectContext *moc = context;
    NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:moc];

    [request setEntity:entity];
    // [request setFetchLimit:1];

    NSArray *propertiesArray = [[NSArray alloc] initWithObjects:idKey, nil];
    [request setPropertiesToFetch:propertiesArray];
    [propertiesArray release], propertiesArray = nil;

    NSSortDescriptor *indexSort = [[NSSortDescriptor alloc] initWithKey:idKey ascending:YES];
    NSArray *array = [[NSArray alloc] initWithObjects:indexSort, nil];
    [request setSortDescriptors:array];
    [array release], array = nil;
    [indexSort release], indexSort = nil;

    NSError *error = nil;
    NSArray *results = [moc executeFetchRequest:request error:&error];
    // NSSLog(@"Autoincrement fetch results: %@", results);
    NSManagedObject *maxIndexedObject = [results lastObject];
    [request release], request = nil;
    if (error) {
        NSLog(@"Error fetching index: %@\n%@", [error localizedDescription], [error userInfo]);
    }
    //NSAssert3(error == nil, @"Error fetching index: %@\n%@", [error localizedDescription], [error userInfo]);

    NSInteger myIndex = 1;
    if (maxIndexedObject) {
        myIndex = [[maxIndexedObject valueForKey:idKey] integerValue] + 1;
    }

    return [NSNumber numberWithInteger:myIndex];
}
10
Lukasz

CoreDataオブジェクトの3種類の一意のID表現は次のとおりです。

NSManagedObjectID *taskID = [task objectID];
NSURL *taskUniqueURLKey = task.objectID.URIRepresentation;
NSString *taskUniqueStringKey = task.objectID.URIRepresentation.absoluteString;

!!!!注:上記の一意のキーをインデックスとして使用する場合は、使用する前にオブジェクトがコンテキストに保存されていることを確認してください。 NSManagedObjectIDクラスのAppleドキュメント:

- (BOOL)isTemporaryID;    // indicates whether or not this ID will be replaced later, 
such as after a save operation (temporary IDs are assigned to newly inserted objects 
and replaced with permanent IDs when an object is written to a persistent store); most
 IDs return NO
6
flypig

を見てみましょう: [[NSProcessInfo processInfo] globallyUniqueString]

Apple docs:プロセスのグローバルID。 IDには、ホスト名、プロセスID、およびタイムスタンプが含まれます。これにより、IDがネットワークで一意であることが保証されます。これは、IDを推測したくない場合に便利です。

6
yooj

データの一意の行に自動インクリメントされたIDを必要とするリモートデータベースと同期したい場合はどうでしょうか?必要に応じて、自動インクリメントされたIDを実装する方法はありますか。コアデータには必要ないことを理解していますが、リモートデータベースからデータをインポートし、再度アップロードして、IDが完全であることを確認する必要があります。

2
marchinram

Swiftの@Lukasz回答の更新:

static func nextAvailble(_ idKey: String, forEntityName entityName: String, inContext context: NSManagedObjectContext) -> Int {
    let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: entityName)
    fetchRequest.propertiesToFetch = [idKey]
    fetchRequest.sortDescriptors = [NSSortDescriptor(key: idKey, ascending: true)]

    do {
        let results = try context.fetch(fetchRequest)
        let lastObject = (results as! [NSManagedObject]).last

        guard lastObject != nil else {
            return 1
        }

        return lastObject?.value(forKey: idKey) as! Int + 1

    } catch let error as NSError {
        //handle error
    }

    return 1 
}
2
Vlad Fedoseev

このような状況ではこれが役立つと思います。

http://lists.Apple.com/archives/cocoa-dev/2006/Jul/msg01801.html maxExistingIDを取得できます。 SO新しいアイテムを保存する際にそれをインクリメントできます

2
S.P.

コアデータは永続化フレームワークに使用され、このフレームワークは主キーを抽象化します。

各NSManagedObjectには、objectIDプロパティで使用可能な固有のキーが組み込まれています。

このIDは、関係を介してエンティティをリンクするために内部的に使用されます。 SQLで使用するのと同じように、主キーとして独自のIDを維持する必要はありません。

NSManagedObject.objectIDでいつでもIDを取得できます。 NSMananagedObjectContext.objectWithIdを使用したオブジェクトコンテキストの取得

1
AmitChauhan