0

Thanks to Kevin for the link, that solved the first issue I was having so I've changed this now just to focus on my remaining problem.

I have a questionnaire app, it has 6 screens laid out like so.

  • Welcome screen with input for user name, dob
  • question 1
  • question 2
  • question 3
  • question 4
  • thank you screen

The problem I'm having is that the data saved from each screen is being saved in to different object ID's in my core data, instead of one.

Here's a screenshot of what I mean using the app Core Data Editor.

EDIT

Here how save data in each controller.

// Save Data
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSManagedObject *q4;
NSString *buttonPressed = [sender titleForState:UIControlStateNormal];
q4 = [NSEntityDescription insertNewObjectForEntityForName:@"Questionnaire" inManagedObjectContext:context];
[q4 setValue:buttonPressed forKey:@"q4"];
Lorenzo B
  • 33,216
  • 24
  • 116
  • 190
Gethin
  • 316
  • 3
  • 15

2 Answers2

0

You have to perform versioning of your data model. Better than that, here is a quick fix..Reset Contents & settings of your simulator. If possible, delete all the files at your application folder. This is happening as you model version has been changed. Know more about versioning here.

Here is a tutorial

Edit
Answer for your updated question is, you are creating a new entry in each viewController. Better handle data from other class & save it ones to your data model after 4th viewController. Let me know if it does not help.

Edit2
Here you dont need to track which button is pressed where. Do one thing, create managed object in your app delegate. now, call that object from each of your view controller when the button is clicked, & update data in same object. In last VC, save the object using context.. It should work.. :)

Here is the code; in AppDelegate.h : @property NSManagedObject *q4;

in AppDelegate.m: (In didFinishLaunchingWithOptions)

q4 = [NSEntityDescription insertNewObjectForEntityForName:@"Questionnaire" inManagedObjectContext:context];

now in implementation of your onClick method call the object like this:

AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[[appDelegate Q4] setValue:buttonPressed forKey:@"q4"];

Finally save it:

AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];

NSManagedObjectContext *context = [appDelegate managedObjectContext];
//here save using context
Lorenzo B
  • 33,216
  • 24
  • 116
  • 190
Prince Agrawal
  • 3,619
  • 3
  • 26
  • 41
  • Ok so I thought thats the way I should do it too, but I can't think how. In each of my views I have code like this to get which button was pressed and then save that as the data, how would I find out which button was pressed from previous views? – Gethin Jan 05 '14 at 18:19
  • i've written code also in my answer. check it. there might be silly mistakes in the code. you can check it though. dont have MAC right now – Prince Agrawal Jan 05 '14 at 18:41
  • I've tried what you've said @flexaddicted I just can't seem to get it fully working. How exactly do you save what button was pressed from each view to the managed object? When I put in the code for AppDelegate.m it gives me errors because 'q4' or context isn't defined, this results in errors everywhere else too. – Gethin Jan 05 '14 at 19:57
0

@achievelimitless is correct. Just save after you finished all the questions. Anyway, the behavior of your app should rely on user expectations. Maybe for 4 questions could be ok, but what about for 100 questions? What if the user stops or close the app after the second question? In this way, he will repeat questions again.

So, a little modification could be to associate to each questionnaire session an identifier. Through the identifier (and the user id, not the name) you could fetch the specific row and so modify it.

Update 1

The problem you have is that in each controller you create a new managed object.

[NSEntityDescription insertNewObjectForEntityForName:@"Questionnaire" inManagedObjectContext:context];

So, at the end you will find as many rows as many object you created during the app.

My preferred way to fix it is to crate the managed object one, for example, after the welcome screen, and pass it to each view controller when you do next.

nextViewController.currentQuestionnaire = [self currentQuestionnaire];

Where each view controller will expose a property like

@property (nonatomic, strong) NSManagedObject* currentQuestionnaire;

When you reach the end, you will do a save. You don't need to access the application delegate to grab the context since each managed object knows the context is registered in.

[[[self currentQuestionnaire] managedObjectContext] save:&error];

Alternatively (I would not follow this approach) you should create a managed object and put it as a reference in the application delegate. By means of this you can access that object like you with

NSManagedObjectContext *context = [appDelegate managedObjectContext];

In other words within each controller

NSManagedObject* currentQuestionnaire = [appDelegate currentQuestionnaire];
// update or save here

Update 2

You need to add each property in each view controller.

So, for example, Q1ViewController would become

@interface Q1ViewController : UIViewController

@property (nonatomic, strong) NSManagedObject* currentQuestionnaire;

@end

Then within this controller, when you are ready to go to the next view controller

 [[self currentQuestionnaire] setValue:@"aValue" forKey:@"q1"];

 Q2ViewController* nextController = // alloc init here
 nextController.currentQuestionnaire = [self currentQuestionnaire];

The creation of a new questionnaire has to be managed in the welcome controller. Here when you are ready to go to question 1, you need to do the following.

NSManagedObject* currentQuestionnaire = [NSEntityDescription insertNewObjectForEntityForName:@"Questionnaire" inManagedObjectContext:context];
// set name and date for the currentQuestionnaire object

// also the screen controller could have a reference to the questionnaire,
// so it will have a property like declared above
self.currentQuestionnaire = currentQuestionnaire;

Q1ViewController* nextController = // alloc init here
nextController.currentQuestionnaire = [self currentQuestionnaire];
Lorenzo B
  • 33,216
  • 24
  • 116
  • 190
  • how do I find out which buttons were pressed from all views in my final view? i'll paste the code I have in each of my views next... – Gethin Jan 05 '14 at 18:24
  • I've tried what you've said @achievelimitless I just can't seem to get it fully working. How exactly do you save what button was pressed from each view to the managed object? – Gethin Jan 05 '14 at 19:56
  • does this go in each view controllers .h files? `@property (nonatomic, strong) NSManagedObject* currentQuestionnaire;` and with this code.. `nextViewController.currentQuestionnaire = [self currentQuestionnaire];` I'm getting an error because of the first 'currentQuestionnaire' saying "property 'currentQuestionnaire' not found on object of type "Q1ViewController" @flexaddicted – Gethin Jan 05 '14 at 20:10
  • thanks for all the help, from update 2 I managed to get it working :) @flexaddicted – Gethin Jan 08 '14 at 00:04