I would like to know if it's possible to init a subclass of NSManagedObject ?
I have a class "Actualite" which is a subclass of NSManagedObject and when I want to initialize this class, I get this error :
"CoreData: error: Failed to call designated initializer on NSManagedObject class Actualite", and the app crashes after this message "-[Actualite setTitre:]: unrecognized selector sent to instance 0x8433be0"
Here is my code :
-(void) recupererActualites {
listeNouvellesActualites = [[NSMutableArray alloc] init];
// Convert the supplied URL string into a usable URL object
NSURL *url = [NSURL URLWithString:FACE06_RSS];
// Create a new rssParser object based on the TouchXML "CXMLDocument" class, this is the
// object that actually grabs and processes the RSS data
CXMLDocument *rssParser = [[CXMLDocument alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding options:0 error:nil];
// Create a new Array object to be used with the looping of the results from the rssParser
NSArray *resultNodes = NULL;
// Set the resultNodes Array to contain an object for every instance of an node in our RSS feed
resultNodes = [rssParser nodesForXPath:#"//item" error:nil];
NSMutableArray* tmp = [[NSMutableArray alloc] init];
for (CXMLElement* resultElement in resultNodes) {
// Create a temporary MutableDictionary to store the items fields in, which will eventually end up in blogEntries
NSMutableDictionary *blogItem = [[NSMutableDictionary alloc] init];
NSMutableArray* categories = [[NSMutableArray alloc] init];
// Create a counter variable as type "int"
int counter;
// Loop through the children of the current node
for(counter = 0; counter < [resultElement childCount]; counter++) {
// Add each field to the blogItem Dictionary with the node name as key and node value as the value
if([[[resultElement childAtIndex:counter] name] isEqual:#"category"])
[categories addObject:[[resultElement childAtIndex:counter] stringValue]];
else {
if ([[resultElement childAtIndex:counter] stringValue] != nil)
[blogItem setObject:[[resultElement childAtIndex:counter] stringValue] forKey:[[resultElement childAtIndex:counter] name]];
else
[blogItem setObject:#"" forKey:[[resultElement childAtIndex:counter] name]];
}
}
Actualite* actu = [[Actualite alloc] init];
[blogItem setObject:categories forKey:#"categories"];
[actu initWithDictionnary:blogItem];
[tmp addObject:actu];
//[actu release];
[categories release];
[blogItem release];
}
listeNouvellesActualites = tmp;
[rssParser release];
resultNodes = nil;
// Stockage des actualités en local
[self stockerActualites];
}
And the initWithDictionary method set all the attributes of the Actualite class.
I also tried
Actualite* actu = [[Actualite alloc] initWithEntity:[NSEntityDescription entityForName:#"Actualite" inManagedObjectContext:managedObjectContext] insertIntoManagedObjectContext:managedObjectContext];
and
Actualite* actu = (Actualite*)[NSEntityDescription entityForName:#"Actualite" inManagedObjectContext:managedObjectContext];
instead of
Actualite* actu = [[Actualite alloc] init];
The errors disappear but the app stops at this point. I don't know what can I do...
Is someone already had this problem ?
Thanks a lot !
The idea is that you ask for a new object to be created inside a context and then you use it:
Actualite* actu = [NSEntityDescription insertNewObjectForEntityForName:#"Actualite" inManagedObjectContext:managedObjectContext];
Related
I setup a background thread with the Parent/Child model. Essentially the context save is failing.
Here is my setup. In the AppDelegate i've setup the _managedObjectContext with the NSMainQueueConcurrencyType:
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];//[[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
In my data loading class I setup the parent/child mocs here to perform the work on the background thread:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSManagedObjectContext *mainMOC = self.managedObjectContext;
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
[moc setParentContext:mainMOC];
[moc setUndoManager:nil];
When the json data has completed I attempt to peform a save operation with the following macro:
#define SAVE_MOC { NSError *error; \
if (![moc save:&error]) { NSLog(#"Sub MOC Error"); } \
[mainMOC performBlock:^{ NSError *e = nil; if (![mainMOC save:&e]) {
NSLog(#"Main MOC Error %#",error.localizedDescription);}}];}
Also when i've completed the data load I jump back on the main thread like this:
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"<---- complete CS sub moc! ---->");
//this fires ok
});
So, from my SAVE_MOC macro i just get a simple error:
Main MOC Error (null)
Let me know if I can provide more info. I'm very new to multi-threading and trying to get a better handle on this approach.
Thanks,
Josh
In my data loading class I setup the parent/child mocs here to perform
the work on the background thread:
dispatch_queue_t queue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSManagedObjectContext *mainMOC = self.managedObjectContext;
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
You should not do that. Do this instead.
NSManagedObjectContext *mainMOC = self.managedObjectContext;
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
Make sure you access the MOC in a performBlock. For example,
[moc performBlock:^{
// Anything at all involving this MOC or any of its objects
}];
When the json data has completed I attempt to peform a save operation
with the following macro:
Consider saving with something like this. Your completion block will be called when the save has finished.
- (void)saveMOC:(NSManagedObjectContext*)moc
completion:(void(^)(NSError *error))completion {
[moc performBlock:^{
NSError *error = nil;
if ([moc save:&error]) {
if (moc.parentContext) {
return [self saveMOC:moc.parentContext completion:completion];
}
}
if (completion) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(error);
});
}
}];
}
[self saveMOC:moc completion:^(NSError *error) {
// Completion handler is called from main-thread, after save has finished
if (error) {
// Handle error
} else {
}
}];
EDIT
This code will crash if moc.parentContext is main concurrency type. –
Mundi
There is no inherent reason that the code I posted should cause a crash with a parent MOC of NSMainQueueConcurrencyType. It has supported being a parent context ever since parent/child was added to Core Data.
Maybe I was missing a typo, so I copy/paste saveMOC:completion: straight from this answer, and wrote the following test helper.
- (void)testWithChildConcurrencyType:(NSManagedObjectContextConcurrencyType)childConcurrencyType
parentConcurrencyType:(NSManagedObjectContextConcurrencyType)parentConcurrencyType {
NSAttributeDescription *attr = [[NSAttributeDescription alloc] init];
attr.name = #"attribute";
attr.attributeType = NSStringAttributeType;
NSEntityDescription *entity = [[NSEntityDescription alloc] init];
entity.name = #"Entity";
entity.properties = #[attr];
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] init];
model.entities = #[entity];
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
[psc addPersistentStoreWithType:NSInMemoryStoreType configuration:nil URL:nil options:nil error:NULL];
NSManagedObjectContext *parent = [[NSManagedObjectContext alloc] initWithConcurrencyType:parentConcurrencyType];
parent.persistentStoreCoordinator = psc;
NSManagedObjectContext *child = [[NSManagedObjectContext alloc] initWithConcurrencyType:childConcurrencyType];
child.parentContext = parent;
NSManagedObject *obj = [NSEntityDescription insertNewObjectForEntityForName:#"Entity" inManagedObjectContext:child];
[obj setValue:#"value" forKey:#"attribute"];
XCTestExpectation *expectation = [self expectationWithDescription:[NSString stringWithFormat:#"save from %# to %# finished", concurrencyTypeString(childConcurrencyType), concurrencyTypeString(parentConcurrencyType)]];
[self saveMOC:child completion:^(NSError *error) {
// Verify data saved all the way to the PSC
NSManagedObjectContext *localMoc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
localMoc.persistentStoreCoordinator = psc;
NSFetchRequest *fr = [NSFetchRequest fetchRequestWithEntityName:#"Entity"];
XCTAssertEqualObjects(#"value", [[[localMoc executeFetchRequest:fr error:NULL] firstObject] valueForKey:#"attribute"]);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:10 handler:nil];
}
And then, I wrote a test for each possible parent/child relationship.
- (void)testThatDoingRecursiveSaveFromPrivateToPrivateWorks {
[self testWithChildConcurrencyType:NSPrivateQueueConcurrencyType
parentConcurrencyType:NSPrivateQueueConcurrencyType];
}
- (void)testThatDoingRecursiveSaveFromPrivateToMainWorks {
[self testWithChildConcurrencyType:NSPrivateQueueConcurrencyType
parentConcurrencyType:NSMainQueueConcurrencyType];
}
- (void)testThatDoingRecursiveSaveFromMainToPrivateWorks {
[self testWithChildConcurrencyType:NSMainQueueConcurrencyType
parentConcurrencyType:NSPrivateQueueConcurrencyType];
}
- (void)testThatDoingRecursiveSaveFromMainToMainWorks {
[self testWithChildConcurrencyType:NSMainQueueConcurrencyType
parentConcurrencyType:NSMainQueueConcurrencyType];
}
So, what am I missing?
As I write this, I am reminded of a 360iDev presentation where the presenter said that you can't call performBlock on a NSMainQueueConcurrencyType context. At the time, I thought he just misspoke, meaning confinement, but maybe there is some confusion in the community about this.
You can't call performBlock on a NSConfinementConcurrencyType MOC, but performBlock is fully supported for NSMainQueueConcurrencyType.
First question here and I've tried a bunch of stuff and can't figure it out.
Core Data with 2 entities with to-many relationship both ways
A<<---->>B
A entity has name as an attribute, and a relationship Bs
First Controller lists all A entities and i have a second controller to add A entities and I want to have it save a default B in its relationship.
In the prepare for segue I have this code:
if ([[segue identifier] isEqualToString:#"addAEntitySegue"]) {
AddAEntityViewController *addAEntityViewController = [segue destinationViewController];
addAEntityViewController.delegate = self;
addAEntityViewController.managedObjectContext = self.managedObjectContext;
NSManagedObjectContext *addingContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
self.addingManagedObjectContext = addingContext;
[addingManagedObjectContext setPersistentStoreCoordinator:[[fetchedResultsController managedObjectContext] persistentStoreCoordinator]];
addAEntityViewController.A = [NSEntityDescription insertNewObjectForEntityForName:#"A" inManagedObjectContext:addingContext];
UIBarButtonItem *saveButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave
target:addAEntityViewController
action:#selector(save:)];
addAEntityViewController.navigationItem.rightBarButtonItem = saveButton;
}
In addAEntityViewController i have this to save
-(IBAction)save:(id)sender
{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"B" inManagedObjectContext:self.managedObjectContext];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == %#",[defaults objectForKey:#"BDefault"]];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:predicate];
//Set the batch size to a suitable number
[fetchRequest setFetchBatchSize:20];
NSError *error;
self.A.name = textFieldVal;
[self.A addBObject:[[self.managedObjectContext executeFetchRequest:fetchRequest error:&error] objectAtIndex:0]];
NSLog(#"A = %#", self.A.Bs);
[self.delegate addAEntityViewController:self didFinishWithSave:YES];
}
In the addAEntityViewController everything saves correctly even the NSLog(#"A = %#", self.A.Bs); statement shows the B. But when the delegate saves in the First Controller (AEntityViewController) it only saves the A.name but not the relationship A.Bs, I can't figure out what's wrong.
Here's the delegate method:
-(void) addAEntityViewController:self didFinishWithSave:YES{
if (save) {
NSLog(#"saveworkouts");
NSError *error;
if (![addingManagedObjectContext save:&error]) {
// Update to handle the error appropriately.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1); // Fail
}
}
// release the adding managed object context
self.addingManagedObjectContext = nil;
}
Like I said it saves the A entity but not the relationship to B even though the relationship to B saved correctly in the addAEntityViewController (the second View). An NSLOg of A.Bs is null.
First I believe that this line:
addAEntityViewController = self.managedObjectContext;
should be:
addAEntityViewController.managedObjectContext = self.managedObjectContext;
but that would also be wrong.
it should be getting the addingContext you created afterwards:
addAEntityViewController.managedObjectContext = addingContext;
I'm a bit surprised that your app didn't crash, as you are mixing managed objects from 2 different contexts.
I need to use some core data managed objects in an NSOperation. The problem is that core data is not thread safe and apparently the object can't be loaded from the new thread. Does anybody know a good tutorial for this? I need the object read only... so the thread will not modify them in any way. Some other, unrelated entities may be added on the main thread while these objects are used in the background, but the background entities don't need to be modified at all..
Hmm seemed I fixed the background running issue, but now the problem is nothing is returned to the delegate... Why? In the thred if I nslog the results are all shown but that call to the delegate never happens
This is the code:
-(void)evaluateFormula:(Formula *)frm runNo:(NSUInteger)runCount{
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue setMaxConcurrentOperationCount:2];
NSManagedObjectID *formulaId = frm.objectID;
for (int i = 0; i < runCount; i++) {
NSInvocationOperation * op = [[NSInvocationOperation alloc] initWithTarget:self selector:#selector(runFormula:) object:formulaId];
[queue addOperation:op];
}
}
-(void)runFormula:(NSManagedObjectID *)fId {
NSManagedObjectContext *thredContext =[[NSManagedObjectContext alloc] init];
NSPersistentStoreCoordinator *coord = (NSPersistentStoreCoordinator *)[(PSAppDelegate *)[[UIApplication sharedApplication] delegate] persistentStoreCoordinator];
[thredContext setPersistentStoreCoordinator:coord];
Formula *f = (Formula *)[thredContext objectWithID:fId];
NSDictionary *vars = [self evaluateVariables:[f.hasVariables allObjects]];
NSMutableString *formula = [NSMutableString stringWithString:f.formula];
for (NSString *var in [vars allKeys]) {
NSNumber *value =[vars objectForKey:var];
[formula replaceOccurrencesOfString:var withString:[value stringValue] options:NSCaseInsensitiveSearch range:NSMakeRange(0, [formula length])];
}
//parse formula
NSNumber *result = [formula numberByEvaluatingString];
// NSLog(#" formula %# result : %d",formula,[result intValue]);
//aggregate results
[self performSelectorOnMainThread:#selector(aggregate:) withObject:result waitUntilDone:YES]; // the delegate doesn't get called ...
}
-(void)aggregate:(NSNumber *)res {
[self.delegate didReceiveResult:res];
}
I'm having trouble saving to one variable letsMeet.startTimeLabel. Right after selecting NSLog shows the correct Value, however, after I save to another variable (letsMeet.endTimeLabel), letsMeet.startTimeLabel changes to (NULL). Below is the code:
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
letsMeet = (LetsMeet *) [NSEntityDescription insertNewObjectForEntityForName:#"LetsMeet" inManagedObjectContext:managedObjectContext];
switch (actionSheet.tag)
{
case 1:
{
if (buttonIndex == 0)
{
UIDatePicker *startDatePicker = (UIDatePicker *)[actionSheet viewWithTag:kDatePickerTag1];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd"];
NSDate *selectedDate = [startDatePicker date];
NSDateFormatter *dayFormatter = [[NSDateFormatter alloc] init];
[dayFormatter setDateFormat:#"EEEE"];
NSDate *selectedDay= [startDatePicker date];
NSDateFormatter *monthFormatter = [[NSDateFormatter alloc] init];
[monthFormatter setDateFormat:#"MMMM"];
NSDate *selectedMonth = [startDatePicker date];
NSString *date = [[NSString alloc] initWithFormat:#"%#", [dateFormatter stringFromDate:selectedDate]];
DateLabel.text = date;
[letsMeet setDateLabel:date];
NSString *month = [[NSString alloc] initWithFormat:#"%#", [dayFormatter stringFromDate:selectedMonth]];
MonthLabel.text = month;
[letsMeet setMonthLabel:month];
NSString *day = [[NSString alloc] initWithFormat:#"%#", [monthFormatter stringFromDate:selectedDay]];
DayLabel.text = day;
[letsMeet setDateLabel:day];
NSDateFormatter *timeFormatter = [[NSDateFormatter alloc] init];
[timeFormatter setDateFormat: #"h:mm a"];
NSDate *selectedStartTime = [startDatePicker date];
NSString *startTime = [[NSString alloc] initWithFormat:#"%#", [timeFormatter stringFromDate:selectedStartTime]];
StartTimeLabel.text = startTime;
[letsMeet setStartTimeLabel:startTime];
NSError *error = nil;
if (![managedObjectContext save:&error]){
NSLog(#"Error Saving");
}
}
NSLog (#"This is the StartTime after selecting %#", letsMeet.startTimeLabel);
}
break;
case 2:
{
if (buttonIndex == 0)
{
UIDatePicker *endTimePicker = (UIDatePicker *)[actionSheet viewWithTag:kDatePickerTag2];
NSDateFormatter *endTimeFormatter = [[NSDateFormatter alloc] init];
[endTimeFormatter setDateFormat: #"h:mm a"];
NSDate *endSelectedTime = [endTimePicker date];
NSString *endTime = [[NSString alloc] initWithFormat:#"%#", [endTimeFormatter stringFromDate:endSelectedTime]];
EndTimeLabel.text = endTime;
[letsMeet setEndTimeLabel:endTime];
NSLog (#"This is the EndTime %#", letsMeet.endTimeLabel);
NSLog (#"This is the StartTime after selecting BOTH %#", letsMeet.startTimeLabel);
}
else if (buttonIndex == 1)
{
EndTimeLabel.text = #"Whenever";
[letsMeet setEndTimeLabel:EndTimeLabel.text];
}
NSError *error = nil;
if (![managedObjectContext save:&error]) {
}
}break;
// Handle the error.
}
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UIViewController *destinationViewController = segue.destinationViewController;
NSLog (#"Prepare For Segue StartTime %#", letsMeet.startTimeLabel);
NSLog (#"Prepare For Segue EndTime%#", letsMeet.endTimeLabel);
}
Here is the log:
2013-02-20 21:38:24.253 AppointmentTime[3129:c07] This is the StartTime after selecting 9:30 AM
2013-02-20 21:38:32.325 AppointmentTime[3129:c07] This is the EndTime 12:15 PM
2013-02-20 21:38:32.325 AppointmentTime[3129:c07] This is the StartTime after Selecting BOTH (null)
2013-02-20 21:38:34.069 AppointmentTime[3129:c07] Prepare For Segue StartTime (null)
2013-02-20 21:38:34.069 AppointmentTime[3129:c07] Prepare For Segue EndTime12:15 PM
Q: Why would letsMeet.startTimeLabel show up correct the first time and after selecting EndTime, it changes to NULL. Please note EndTime continues to show the correct Value all the way up to prepareForSegue. Weird!
According to your logs and code , you are entering the switch block twice. Which means you are entering the actionSheet:clickedButtonAtIndex: method twice. So each time you enter the method
letsMeet = (LetsMeet *) [NSEntityDescription insertNewObjectForEntityForName:#"LetsMeet" inManagedObjectContext:managedObjectContext];
statement is executed twice, in turn creating two objects. You can see this by doing a fetch from the store.
So you are checking for properties in two different objects and hence the null.
If you are using just one managed object, you can probably add a check for nil for the object before executing insertNewObjectForEntityForName:inManagedObjectContext:. This will make sure you are using the same object.
If you are using more than one object at the same time use the object id or some unique key to identify your object and manipulate it.
Edit:
You can check for nil with the following code:
if(letsMeet==Nil){
letsMeet = (LetsMeet *) [NSEntityDescription insertNewObjectForEntityForName:#"LetsMeet" inManagedObjectContext:managedObjectContext];
}
This will work only, if the object you are calling the actionSheet:clickedButtonAtIndex: method is always in memory. But since you are persisting you might want to fetch the object from the store and then check for no. of objects.
NSError *error;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"LetsMeet" inManagedObjectContext:managedObjectContext]];
NSArray *objectArray = [managedObjectContext executeFetchRequest:request error:&error]
if(objectArray.count==0){
letsMeet = (LetsMeet *) [NSEntityDescription insertNewObjectForEntityForName:#"LetsMeet" inManagedObjectContext:managedObjectContext];
}else{
letsMeet = (LetsMeet *)[objectArray objectAtIndex:0];
}
Note: If you need to persist only a couple of variables, core-data might be an overkill. Use NSUserDefaults instead and keep it simple.
I have been trying to add an object as an NSMutableDictionary to my array, which I am accessing from another view, and It doesn't seem to work. I want to be able to store the data in a plist which I access from a NSDictionary.
-(void)saveAlarm:(id)sender {
// Adding object for alarm to AlarmViewController
alarmArrayCopy = alarmViewController.alarmsTime;
NSMutableDictionary *newAlarm = [[NSMutableDictionary alloc] init];
[newAlarm setValue:labelTextField.text forKey:LABEL_KEY];
[newAlarm setValue:alarmPicker.date forKey:TIME_KEY];
[alarmArrayCopy addObject:(newAlarm)];
// Dismissing and tiding up.
[self.navigationController dismissModalViewControllerAnimated:YES];
[newAlarm release];
}
UPDATE: How do I add an NSDictionary to my plist database (my db is an array)?
Here is some new code, I updated the NSMutableDictionary to NSDictionary because in my plist you can only have normal dictionaries not a mutable one. But now it crashed and gives me a Thread 1:Program received signal: "SIGABRT".
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathComponent:#"data.plist"];
// Adding object for alarm to AlarmViewController
NSDictionary *newAlarm = [[NSDictionary alloc] init];
[newAlarm setValue:labelTextField.text forKey:LABEL_KEY];
[newAlarm setValue:[NSString stringWithFormat:#"%#", alarmPicker.date] forKey:TIME_KEY];
[newAlarm writeToFile:finalPath atomically:NO];
or
-(IBAction)saveAlarm:(id)sender {
// Adding object for alarm to AlarmViewController
NSString *time = [NSString stringWithFormat:#"%#", alarmPicker.date];
NSString *label = [NSString stringWithFormat:#"%#",labelTextField.text];
NSDictionary *newAlarm = [[NSDictionary alloc] initWithObjectsAndKeys:label, LABEL_KEY,time, TIME_KEY, nil];
self.alarmArrayCopy = alarmViewController.alarmsTime;
[alarmArrayCopy addObject:(newAlarm)];
// Dismissing and tiding up.
[newAlarm release];
[self.navigationController dismissModalViewControllerAnimated:YES];
}
First, you should use setObject:forKey: method for adding objects to NSMutableDictionary. Second, you should use initWithObjectsAndKeys: method if you are using NSDictionary.
The setValue:forKey is a method of the Key Value Coding protocol. That was described at here “
Where's the difference between setObject:forKey: and setValue:forKey: in NSMutableDictionary?
”
So, you should do that,
NSDictionary *newAlarm = [[NSDictionary alloc] initWithObjectsAndKeys:
labelTextField.text, LABEL_KEY,
alarmPicker.date, TIME_KEY, nil];
[newAlarm setValue:alarmPicker.date forKey:TIME_KEY];
I am not quite sure, but I guess your error is because you can't send an instance of NSDate object to setValue:forKey method. You may use either setObject:forKey or change NSDate to NSString by [NSString stringWithFormat:"%#", alarmPicker.date].
Hope that helps.