Reputation: 1553
I have a user table and a girls table and a girls_result table.
Basically I want only one user in USER
entity, that USER is the device owner, and I want to call that same USER every time I need it.
USER can have multiple girls, and girls can have multiple results.
Data Model:
USER <------>>GIRLS<-------->>GIRLS_RESULTS
So I added user_deviceid attribute to USER Entity and created a singleton class so I can set a unique number for the user , and call it when I need it. I want to make sure multiple user objects with same UUID is not created.
@implementation SingletonClass
@synthesize singletonManagedObjectContext=_singletonManagedObjectContext;
@synthesize userIS=_userIS;
+ (SingletonClass *)sharedInstance
{
static SingletonClass *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[SingletonClass alloc] init];
// Do any other initialisation stuff here
});
return sharedInstance;
}
- (id)init {
if (self = [super init]) {
// set a singleton managed object context
_singletonManagedObjectContext=self.singletonManagedObjectContext;
//set only one user based on unique device id, so all tables will belong to that user
NSManagedObjectContext *context = _singletonManagedObjectContext;
//how to make sure that _userIS is the same user all the time???
if (_userIS.user_deviceid == [self newUUID]) {
NSLog(@"user dvice id matches");
}
else{
_userIS.user_deviceid=[self newUUID];
}
}
return self;
}
- (NSString *)newUUID
{
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
return (NSString *)CFBridgingRelease(string);
}
So How can I make sure that only one USER is created in USER entity and I can use that specific USER each time?
============EDIT ANSWER============ Based On Accepted Answer Below I have created a class it works fine
#import "CheckUser.h"
#import "USER.h"
#import "SingletonClass.h"
@implementation CheckUser
- (USER *)checkandreturnUser
{
SingletonClass *sharedInstance = [SingletonClass sharedInstance];
NSManagedObjectContext *context = sharedInstance.singletonManagedObjectContext;
// Fetch Form Object
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"USER"
inManagedObjectContext:context]];
USER *user;
NSError *error = nil;
NSArray *userArray = [context executeFetchRequest:fetchRequest error:&error];
NSLog(@"user array count %i",[userArray count]);
if (userArray == nil) {
NSAssert(0, @"There was an error fetching user object");
userArray = [NSArray array];
}
// If user doesn't exist create it
if ([userArray count] > 0) {
NSAssert([userArray count] == 1, @"Expected one user but there were more");
user = [userArray objectAtIndex:0];
} else {
//Create user object
user = [NSEntityDescription insertNewObjectForEntityForName:@"USER"
inManagedObjectContext:context];
user.user_deviceid=[self newUUID];
// maybe save here?
if (![context save:&error]) {
NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
}
}
return user;
}
- (NSString *)newUUID
{
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
return (NSString *)CFBridgingRelease(string);
}
Upvotes: 2
Views: 2743
Reputation: 2700
The easiest solution is to probably check and make sure that you don't create more than one USER. Once you have one user entity just stop.
[self newUUID]
will always return a different value so _userIS.user_deviceid == [self newUUID]
would always be NO
I would use an accessor for _userIS
- (NSManagedObject *)user
{
if (_userIS) {
return _userIS;
}
NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"user"
inManagedObjectContext:_singletonManagedObjectContext]];
NSError *error = nil;
NSArray *userArray = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (userArray == nil) {
NSAssert(0, @"There was an error fetching user object");
userArray = [NSArray array];
}
// If user doesn't exist create it
if ([userArray count] > 0) {
NSAssert([userArray count] == 1, @"Expected one user but there were more");
_userIS = [userArray objectAtIndex:0];
} else {
//Create user object
_userIS = [NSEntityDescription insertNewObjectForEntityForName:@"user"
inManagedObjectContext:_singletonManagedObjectContext];
_userIS.user_deviceid=[self newUUID];
// maybe save here?
}
[_userIS retain]; // Non-ARC only
return _userIS;
}
Its also worth mentioning that having a root object is not uncommon and is part or the Model-View-Controller-Store pattern.
Upvotes: 2
Reputation: 7381
You should override - (id)initWithEntity:(NSEntityDescription *)entity insertIntoManagedObjectContext:(NSManagedObjectContext *)context
, not init
. Assuming your model object name is User, it would look like this
- (id) initWithEntity:(NSEntityDescription *)entity
insertIntoManagedObjectContext:(NSManagedObjectContext *)context
static User * _Singleton = nil;
if (!_Singleton)
{
self = [super initWithEntity:entity
insertIntoManagedObjectContext:context];
}
return self;
Upvotes: 0
Reputation: 70956
Core Data doesn't support the idea of a singleton entity. If you want to have just one instance of an entity in your data store, you need to write your app to make sure that you never create more than one.
The reason for this is simply that it's a bizarre proposition that doesn't fit with the idea of a data store. If you only have one instance, you don't need to use Core Data for that instance. Save your singleton data in user defaults or in a custom file. Putting it in the data store doesn't make a lot of sense. You don't need relationships between it and other objects because you always know what those relationships are-- they're not configurable, they don't need to be looked up, so they don't need to exist.
Upvotes: 11