Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a unique id for a Core Data program on the iPhone

People also ask

How do you make a core data attribute unique with constraints?

If you look in the Data Model inspector you'll see a field marked "Constraints" – click the + button at the bottom of that field. A new row will appear saying "comma,separated,properties". Click on that, hit Enter to make it editable, then type "sha" and hit Enter again. Make sure you press Cmd+S to save your changes!

What is core data on iPhone?

Core Data is a framework that you use to manage the model layer objects in your application. It provides generalized and automated solutions to common tasks associated with object life cycle and object graph management, including persistence.

What is an Nsmanagedobjectid?

A compact, universal identifier for a managed object.


Though i agree with what you said, there is an ID mechanism behind core data. ID are indeed managed by Core-Data but you can retrieve them with :

NSManagedObjectID *moID = [managedObject objectID];

For more informations see : Core Data Programming Guide


That ain't how CoreData works.

In CoreData, you create instances of entities. Each instance is unique. You then retrieve and manipulate instances as needed. CoreData takes care of the persistence for you, including uniquely identifying instances.

Step away from everything you know about traditional relational databases.

CoreData is an awesomely powerful bit of technology that offers features well beyond just database like persistence. It'll save you many lines of code and perform extremely well if you embrace it.


This class function will return next available number for your id property (it must be integer property).

I call it auto-increment value generator. I still agree with others that there is objectID for that but sometimes you just need number.

You can put this function in your NSManagedObject subclass for the entity:

+(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];
}

Swift 5.0

func nextAvailble(_ idKey: String, forEntityName entityName: String, in context: NSManagedObjectContext) -> NSNumber? {

    let req = NSFetchRequest<NSFetchRequestResult>.init(entityName: entityName)
    let entity = NSEntityDescription.entity(forEntityName: entityName, in: context)
    req.entity = entity
    req.fetchLimit = 1
    req.propertiesToFetch = [idKey]
    let indexSort = NSSortDescriptor.init(key: idKey, ascending: false)
    req.sortDescriptors = [indexSort]

    do {
        let fetchedData = try context.fetch(req)
        let firstObject = fetchedData.first as! NSManagedObject
        if let foundValue = firstObject.value(forKey: idKey) as? NSNumber {
            return NSNumber.init(value: foundValue.intValue + 1)
        }

        } catch {
            print(error)

        }
    return nil

}

Here are three kinds of unique ID representation of CoreData object:

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

!!!!Note: if you want to use above unique key as index, please make sure the object is saved to context before using it , or the objectID would be a temporary Id, which will be replaced later (e.g. after saved). See the apple document of NSManagedObjectID class :

- (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

Take a look at NSProcessInfo / ProcessInfo from where we can fetch unique id.

Objective-C code snippet:

[[NSProcessInfo processInfo] globallyUniqueString].

Swift code snippet:

let uniqueId = ProcessInfo().globallyUniqueString
print("uniqueId: \(uniqueId)")

Screenshot

Apple Docs:

Global ID for the process. The ID includes the host name, process ID, and a time stamp, which ensures that the ID is unique for the network, which is handy if you don't want people guessing the id.


Core data is used for persistance framework, this framework abstracts the primary key.

Each NSManagedObject has its own unique key built in which is available in its objectID property.

This id is internally used to link entities over its relations. There is no need to maintain an own id as a primary key as you are used to do in SQL.

You can always get the id by NSManagedObject.objectID. and fetching object context using NSMananagedObjectContext.objectWithId