objective c Core Data - Attributes aren't saved persistent - objective-c

i need help!!!^^
I write in my attributes (name,prename) the two names of the person and save them. If i try to access the attrubutes in another view then they are nil. I don't understand why?!?
I did it this way. I get the profileContext with the method getProfile and i access the Attributes with the Dot-Notation, then i save it. My NSLog show me the right name and my fetch too.
ownProfile = [[MyProfile alloc] init];
profileContext = [ownProfile getProfile];
ownProfile = (MyProfile*)[NSEntityDescription insertNewObjectForEntityForName:#"MyProfile" inManagedObjectContext:profileContext];
ownProfile.Vorname = #"Max";
ownProfile.Nachname = #"Wilson";
NSLog(#"%#",ownProfile.Nachname);
if ([profileContext hasChanges]) {
NSLog(#"It has changes!");
[profileContext save:nil];
}
//Fetching
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"MyProfile" inManagedObjectContext:profileContext];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];
NSArray *array = [profileContext executeFetchRequest:request error:nil];
for (int i=0; i < [array count]; i++) {
MyProfile *object = [array objectAtIndex:i];
NSLog(#"Name: %#",object.Nachname);
}
if i try to access the attributes in another ViewController subclass they are nil. This is the code:
- (void)viewDidLoad {
[super viewDidLoad];
ownProfile = [[MyProfile alloc] init];
NSManagedObjectContext *profileContext = [ownProfile getProfile];
ownProfile = [NSEntityDescription insertNewObjectForEntityForName:#"MyProfile" inManagedObjectContext:profileContext];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"MyProfile" inManagedObjectContext:profileContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];
[request setIncludesPropertyValues:NO]; //only fetch the managedObjectID
NSArray *array = [profileContext executeFetchRequest:request error:nil];
[request release];
MyProfile *object = [array objectAtIndex:[array count]-1];
NSLog(#"%#",object);
}
my getProfile method is in the NSManagedObjectClass and look like this:
-(NSManagedObjectContext*) getProfile {
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],
NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES],
NSInferMappingModelAutomaticallyOption, nil];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
NSLog(#"basePath = %#",basePath);
NSURL *storeUrl = [NSURL fileURLWithPath:[basePath stringByAppendingFormat:#"CoreData.sqlite"]];
NSPersistentStoreCoordinator *persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[NSManagedObjectModel mergedModelFromBundles:nil]];
NSLog(#"PersistentStore = %#",persistentStoreCoordinator);
NSError *error = nil;
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
NSLog(#"error loading persistent store..");
[[NSFileManager defaultManager] removeItemAtPath:storeUrl.path error:nil];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
NSManagedObjectContext *profile = [[NSManagedObjectContext alloc] init];
[profile setPersistentStoreCoordinator:persistentStoreCoordinator];
return profile;
}
Please help me!!!^^

Hey guys...I solved my problem!!! :)
My fault was that I add in the viewDidLoad-Method in the line
ownProfile = [NSEntityDescription insertNewObjectForEntityForName:#"MyProfile" inManagedObjectContext:profileContext];
another object in the persistentStore and i was always reading the new object where the attributes are nil...of course^^

Related

Unit testing with core data in objective c

My coredata methods are here. How to write unit test case to check this.
Method to save to coredata
- (void)saveUserDetails:(Model *)userDetail {
if(userDetail != nil) {
UserEntity *user = [NSEntityDescription insertNewObjectForEntityForName:#“EntityName” inManagedObjectContext:[self sharedContext]];
NSArray *fetchArray = [self fetchUserWithUsername:userDetail.username];
if ([fetchArray count] == 0) {
user.username = userDetail.username;
[self saveContext];
}
}
}
Method to fetch from coredata
- (NSArray *)fetchUserWithUsername:(NSString *)username {
if (username != nil) {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *userEntity = [NSEntityDescription entityForName:#“EntityName” inManagedObjectContext:[self sharedContext]];
[fetchRequest setEntity:userEntity];
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"username = %#", username];
NSError *error;
NSArray *fetchedObjects = [[self sharedContext] executeFetchRequest:fetchRequest error:&error];
return fetchedObjects;
}
return nil;
}
Create an in-memory store and inject this into your object.
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"MyResource" withExtension:#"momd"];
NSManagedObjectModel *mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
XCTAssertTrue([psc addPersistentStoreWithType:NSInMemoryStoreType configuration:nil URL:nil options:nil error:NULL] ? YES : NO, #"Should be able to add in-memory store");
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
context.persistentStoreCoordinator = psc;

Core Data managed object context save not working

I am trying to write data to persistent storage with managed object context. inserting simple static data. save is returning no errors but fetch is not returning any results. here is my code:
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"MyDB" withExtension:#"momd"];`
NSManagedObjectModel *mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSAssert(mom!=nil, #"Error in initializing Managed Object Model");
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[moc setPersistentStoreCoordinator:psc];
[self setManagedObjectContext:moc];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *documentsURL = [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSURL *storeURL = [documentsURL URLByAppendingPathComponent:#"MyDB.sqllite"];
NSError *error = nil;
NSPersistentStoreCoordinator *pscStore = [moc persistentStoreCoordinator];
NSPersistentStore *store = [pscStore addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error];
NSAssert(store!=nil,#"Error in initializing PSC:%#\n%#",[error localizedDescription],[error userInfo]);
//insert
Schedule *schedule = [NSEntityDescription insertNewObjectForEntityForName:#"Schedule" inManagedObjectContext:moc];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd-MM-yyyy"];
NSDate *sessionEndDateReturned = [NSDate alloc];
sessionEndDateReturned = [dateFormatter dateFromString:#"24-04-2016"];
NSDate *sessionStartDateReturned = [NSDate alloc] ;
sessionStartDateReturned = [dateFormatter dateFromString:#"25-04-2016"];
//schedule.category = #"cat";
schedule.about = #"testabout";
schedule.endDate = sessionEndDateReturned;
schedule.eventId = #"e1";
schedule.sessionID = #"s1";
schedule.roomNumber = #"r1";
schedule.startDate = sessionStartDateReturned;
schedule.topic = #"topic1";
schedule.type = #YES;
NSLog(#"inserted objs:%#",moc.insertedObjects);
//save
NSError *insertError = nil;
if(![moc save:&insertError]){
NSLog(#"%# %#",insertError,insertError.localizedDescription);
}
//fetch
NSFetchRequest *fetchReq = [NSFetchRequest fetchRequestWithEntityName:#"Schedule"];
NSError *fetchError = nil;
NSArray *result =[moc executeRequest:fetchReq error:&fetchError];
if(fetchError){
NSLog(#"fetch Error: %#",fetchError.localizedDescription);
}
else
{
NSLog(#"myFetch Result:%#",result);
}
can anybody tell me where i am going wrong?
everything is fine in the above code except fetching part. only small change is required. Save is happening fine, problem only with fetch.
change the fetch execute with below line:
NSArray *result =[moc executeFetchRequest:fetchReq error:&error];
I was doing executeRequest instead of executeFetchRequest :|

Recipes to update database in Core Data

I have a method for adding stamp to the card, from QR code reader to web service
my question is,
Here is my code:
- (void)addStamp
{
NSString *url = [_URL stringByAppendingString:#"add-stamp"];
NSString *post = [NSString stringWithFormat:#"userId=%#&code=%#", self.userId, self.code ];
post = [post stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSData *postData = [NSData dataWithBytes:[post UTF8String]
length:[post lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL
URLWithString:url] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:600];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:postData];
}
Rightnow I want to update my DB with new method -> if the code is repeated add stamp, if not create add a new card:
-(void)addStampInDB:(int)cardId
{
NSManagedObjectContext* managedObjectContext = [(AppDelegate*) [[UIApplication
sharedApplication] delegate] managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Card"
inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"remote_id = %d", cardId];
[fetchRequest setPredicate:predicate];
[managedObjectContext lock];
NSError *error;
NSArray *fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest
error:&error];
[managedObjectContext unlock];
Card *d = nil;
if([fetchedObjects count] > 0 ){
d = [fetchedObjects objectAtIndex:0];
cardId++;
} else{
d = [NSEntityDescription insertNewObjectForEntityForName:#"Card"
inManagedObjectContext:managedObjectContext];
}
NSArray *test;
for(NSDictionary *stamp in test)
{
d.remote_id = [NSNumber numberWithInt:[[stamp objectForKey:#"id"] intValue]];
d.stampNumber = [NSNumber numberWithInt:[[stamp objectForKey:#"stampNumber"] intValue]];
d.createdAt = [NSDate dateWithTimeIntervalSince1970:[[stamp objectForKey:#"createdAt"]
intValue]];
[managedObjectContext lock];
NSError *error;
if (![managedObjectContext save:&error])
{
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
NSLog(#"Failed to save to data store: %#", [error localizedDescription]);
NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
if(detailedErrors != nil && [detailedErrors count] > 0) {
for(NSError* detailedError in detailedErrors) {
NSLog(#" DetailedError: %#", [detailedError userInfo]);
}
} else {
NSLog(#" %#", [error userInfo]);
}
}
[managedObjectContext unlock];
}
}
I don't know if I'm in a right way or not and also how I can test my method?
I'm not very sure about your question but I'll try to give some hints.
First
Card *d = nil;
if([fetchedObjects count] > 0 ){
d = [fetchedObjects objectAtIndex:0];
cardId++;
} else{
d = [NSEntityDescription insertNewObjectForEntityForName:#"Card"
inManagedObjectContext:managedObjectContext];
}
Here you have found an existing card, you use it, else you create a new. Question: what about cardId? Where is it used?
Second
for(NSDictionary *stamp in test)
{
d.remote_id = [NSNumber numberWithInt:[[stamp objectForKey:#"id"] intValue]];
d.stampNumber = [NSNumber numberWithInt:[[stamp objectForKey:#"stampNumber"] intValue]];
d.createdAt = [NSDate dateWithTimeIntervalSince1970:[[stamp objectForKey:#"createdAt"]
intValue]];
// other code here
}
If you loop test, you overwrite the value of your card d each time. Is it right?
Third
for(NSDictionary *stamp in test)
{
// other code here
}
// save here
Move the save out of the for loop. This boost performances in your app. It is not necessary to save each time in your loop. Do it at the end only.
Hope that helps.
P.S. If you want to know something else let me know.

executeFetchRequest:error A fetch request must have an entity

I am getting error in the search part. when i enter the song name i should get the lyrics there but getting an error says 'executeFetchRequest:error: A fetch request must have an entity.' i used the following code
-(void)findLyrics
{
LyricsAppDelegate *appDelegate = [[UIApplication sharedApplication]
delegate];
NSManagedObjectContext *managedObjectContext = [appDelegate managedObjectContext];
NSEntityDescription *entityDesc = [NSEntityDescription
entityForName:#"Lyrics"inManagedObjectContext:managedObjectContext];
NSManagedObject *LyricsObjectEnglish;
LyricsObjectEnglish = [NSEntityDescription insertNewObjectForEntityForName:#"English_Songs"
inManagedObjectContext:managedObjectContext];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDesc];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"(MovieSongName = %#)",song_name.text];
[request setPredicate:pred];
NSManagedObject *matches = nil;
NSError *error;
NSArray *objects = [managedObjectContext executeFetchRequest:request error:&error];
if ([objects count] == 0)
{
//status.text = #"No matches";
} else {
matches = [objects objectAtIndex:0];
song_lyrics.text = [matches valueForKey:#"SongLyrics"];
song_name.text = [matches valueForKey:#"MovieSongName"];
// status.text = [NSString stringWithFormat:#"%d matches found", [objects count]];
}
[request release];
}
Any body please help..

NSLog and Core Data

I have three Classes for which I am extending NSManagedObject (I know this isn't required but I wanted the property notation). Theses Classes are QuestionSet, Question and Answer. My data model is setup so that there's a many to many between them like so: QuestionSet <<->> Question <<->> Answer. I load up everything from a server and it save successfully meaning I look in the .db file and it's all how I expect, if I immediately NSLog the array questionsets they look great and if I go take a quiz it works great.
However if I NSLog that array anywhere but right after where I load them from the server, it crashes my app. The quiz still runs fine so I know the data is in there and in the expected format. Does this have something to do with Core Data clearing out space and then my relationships don't 'lazy loaded' when I'm just trying to log them? Sorry, still wrapping my head around core data.
This bit works, I load from the server and at the bottom I 'loadTrivia' and log what I get. The issue comes if at sometime later during the course of the app execution, an NSLog of the questionsets will fail.
- (void)loadQuestionSetFromNetworkWithID:(NSNumber *)p_id andTitle:(NSString *)p_title
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:kTriviaQuestionSetURL, [p_id intValue]]]];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
NSString *json_string = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSArray *questions = [[[sbjson objectWithString:json_string error:nil] valueForKeyPath:#"Q"] objectAtIndex:0];
NSError *error;
NSFetchRequest *questionsetRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *questionsetEntity = [NSEntityDescription entityForName:#"QuestionSet" inManagedObjectContext:[self managedObjectContext]];
NSPredicate *questionsetPredicate = [NSPredicate predicateWithFormat:#"id = %d", [p_id intValue]];
[questionsetRequest setEntity:questionsetEntity];
[questionsetRequest setPredicate:questionsetPredicate];
QuestionSet *qs = nil;
NSArray *questionSetObjects = [[self managedObjectContext] executeFetchRequest:questionsetRequest error:&error];
if (questionSetObjects == nil){
// Handle errors
}
if ([questionSetObjects count] > 0)
qs = [questionSetObjects objectAtIndex:0];
else
qs = [NSEntityDescription insertNewObjectForEntityForName:#"QuestionSet" inManagedObjectContext:[self managedObjectContext]];
qs.id = p_id;
qs.title = p_title;
for (int i = 0; i < [questions count]; i++)
{
NSFetchRequest *questionRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *questionEntity = [NSEntityDescription entityForName:#"Question" inManagedObjectContext:[self managedObjectContext]];
NSPredicate *questionPredicate = [NSPredicate predicateWithFormat:#"(id = %d)", [[[questions objectAtIndex:i] objectForKey:#"id"] intValue]];
[questionRequest setEntity:questionEntity];
[questionRequest setPredicate:questionPredicate];
Question *q = nil;
NSArray *questionObjects = [[self managedObjectContext] executeFetchRequest:questionRequest error:&error];
if (questionObjects == nil){
// Handle errors
}
if ([questionObjects count] > 0)
q = [questionObjects objectAtIndex:0];
else
q = [NSEntityDescription insertNewObjectForEntityForName:#"Question" inManagedObjectContext:[self managedObjectContext]];
q.id = [NSNumber numberWithInt:[[[questions objectAtIndex:i] objectForKey:#"id"] intValue]];
q.question = [[questions objectAtIndex:i] objectForKey:#"text"];
q.answer = [NSNumber numberWithInt:[[[questions objectAtIndex:i] objectForKey:#"ca"] intValue]];
for (int j = 0; j < [[[questions objectAtIndex:i] objectForKey:#"A"] count]; j++)
{
NSFetchRequest *answerRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *answerEntity = [NSEntityDescription entityForName:#"Answer" inManagedObjectContext:[self managedObjectContext]];
NSPredicate *answerPredicate = [NSPredicate predicateWithFormat:#"(id = %d)", [[[[[questions objectAtIndex:i] objectForKey:#"A"] objectAtIndex:j] objectForKey:#"id"] intValue]];
[answerRequest setEntity:answerEntity];
[answerRequest setPredicate:answerPredicate];
Answer *a = nil;
NSArray *answerObjects = [[self managedObjectContext] executeFetchRequest:answerRequest error:&error];
if (answerObjects == nil){
// Handle errors
}
if ([answerObjects count] > 0)
a = [answerObjects objectAtIndex:0];
else
a = [NSEntityDescription insertNewObjectForEntityForName:#"Answer" inManagedObjectContext:[self managedObjectContext]];
a.id = [NSNumber numberWithInt:[[[[[questions objectAtIndex:i] objectForKey:#"A"] objectAtIndex:j] objectForKey:#"id"] intValue]];
a.answer = [[[[questions objectAtIndex:i] objectForKey:#"A"] objectAtIndex:j] objectForKey:#"text"];
a.questions = [a.questions setByAddingObject:q];
q.answers = [q.answers setByAddingObject:a];
[answerRequest release];
}
q.questionsets = [q.questionsets setByAddingObject:qs];
qs.questions = [qs.questions setByAddingObject:q];
[questionRequest release];
}
[questionsetRequest release];
[[self managedObjectContext] save:&error];
[json_string release];
[self loadTrivia];
NSLog(#"After Load: %#", self.questionsets);
}
This function fetches all the QuestionSet objects from the db and stores the array in an ivar.
- (BOOL)loadTrivia
{
NSError *error;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"QuestionSet" inManagedObjectContext:[self managedObjectContext]];
[request setEntity:entity];
self.questionsets = [[self managedObjectContext] executeFetchRequest:request error:&error];
return YES;
}
Just for completeness, here are my description methods in my classes
from QuestionSet.h
- (NSString *)description
{
return [NSString stringWithFormat:#"\
\n\tid: %#\
\n\ttitle: %#\
\n\tquestions: %#\n",
self.id,
self.title,
self.questions];
}
from Question.h
- (NSString *)description
{
return [NSString stringWithFormat:#"\
\n\tid: %#\
\n\tanswer: %#\
\n\tquestion: %#\
\n\tanswers: %#\n",
self.id,
self.answer,
self.question,
self.answers];
}
from Answer.h
- (NSString *)description
{
return [NSString stringWithFormat:#"\
\n\tid: %#\
\n\tanswer: %#\n",
self.id,
self.answer];
}
You shouldn't subclass the description method (Link):
Although the description method does not cause a fault to fire, if you implement a custom description method that accesses the object’s persistent properties, this will cause a fault to fire. You are strongly discouraged from overriding description in this way.
I tested your loadTrivia code (with a different entityName) on my app and it worked fine.
Did you have a look at the NSError (you should initialize it with =nil):
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
Also you should release the NSFetchRequest after execution in - (BOOL)loadTrivia.