I'm trying to get the first letter of an attribute (autor) from my pre populated sqlite database. I have no problems retriving data from the database using coredata. But when I try to get data from my transient property, I get this error message: "NSFetchedResultsController ERROR: object { Autor = "\U00cdtalo Calvino"; } returned nil value for section name key path 'FirstLetter'. Object will be placed in unnamed section"...
I have created a transient attribute called FirstLetter and inside my entity Cit. I have also my class for the entity defined.
Cit.h
#interface Cit : NSManagedObject {
#private
}
#property (nonatomic, retain) NSString * Autor;
#property (nonatomic, retain) NSString * FirstLetter;
- (NSString *) FirstLetter;
#end
Cit.m
#import "Cit.h"
#implementation Cit
#dynamic Autor;
#dynamic FirstLetter;
- (NSString *) FirstLetter {
NSLog(#"doing");
[self willAccessValueForKey:#"FirstLetter"];
NSString * initial = [[self valueForKey:#"Autor"] substringToIndex:1];
[self didAccessValueForKey:#"FirstLetter"];
return initial;
}
#end
I cannot get the it to work. Does anyone have a solution for that??? thanks!
I did something similar in my model class, but I didn't bother creating a transient object in the model. I just added a - (NSString *)sectionIndex method to my model that returned the first letter of the string, same as you.
So, I'd try deleting the transient attribute from your model and see if that works any better.
Related
H file:
#interface TaskTypeEntity : NSManagedObject
#property (nonatomic, retain) UIColor *color;
#property (nonatomic, retain) UIImage *image;
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) NSNumber * status;
#property (nonatomic, retain) NSSet *task;
#property (nonatomic, retain) NSSet *taskCount;
#end
M file:
#implementation TaskTypeEntity
#dynamic color;
#dynamic image;
#dynamic name;
#dynamic status;
#dynamic task;
#dynamic taskCount;
- (void) add:(TaskTypeEntity*)data
{
TaskTypeEntity *taskTypeEntity = [NSEntityDescription insertNewObjectForEntityForName:ENTITY_NAME inManagedObjectContext:content];
taskTypeEntity.name = data.name;
taskTypeEntity.image = data.image;
taskTypeEntity.color = data.color;
BOOL result = [content save:nil];
if (result) {
NSLog(#"success%#", data);
}else{
NSLog(#"fail");
}
}
#end
When setting the property, It doesn't work:
TaskTypeEntity *taskTypeEntity = [TaskTypeEntity alloc];
taskTypeEntity.name = #"dfdfd";
[taskTypeModel add:taskTypeEntity];
error:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[TaskTypeEntity setName:]: unrecognized selector sent to instance 0x8a7b070'
Please help me, thank you
According to the NSManagedObject class reference:
Important: This method is the designated initializer for
NSManagedObject. You must not initialize a managed object simply by
sending it init.
The method of reference in the above quoted text is insertNewObjectForEntityForName:inManagedObjectContext: and can be used thusly:
NSManagedObject *object = [NSEntityDescription
insertNewObjectForEntityForName:#"Item"
inManagedObjectContext:context];
EDIT (In response...)
This code is just plain wrong:
TaskTypeEntity *taskTypeEntity = [TaskTypeEntity alloc];
Even if TaskTypeEntity were not a NSManagedObject it would still be wrong, as you never called an initializer.
The fact that it is a NSManagedObject makes it even more wrong, because you are never supposed to alloc/init one of those.
Why not try something like this (I assume you are using transformable attributes for image and color):
+ (instancetype)taskTypeEntityInMOC:(NSManagedObjectContext*)context
name:(NSString*)name
image:(UIImage*)image
color:(UIColor*)color
{
TaskTypeEntity *taskTypeEntity = [NSEntityDescription insertNewObjectForEntityForName:ENTITY_NAME inManagedObjectContext:content];
taskTypeEntity.name = name;
taskTypeEntity.image = image;
taskTypeEntity.color = color;
return taskTypeEntity;
}
Then you can call it...
TaskTypeEntity *taskTypeEntity =
[TaskTypeEntity taskTypeEntityInMOC:context
name:(NSString*)name
image:(UIImage*)image
color:(UIColor*)color];
In order to wrap some logic to model, I plan to put NSManagedObjectContext in one NSManagedObject model, so I can handle many common logic in one model:
#interface Collect : NSManagedObject{
NSManagedObjectContext *managedObjectContext;
}
#property (nonatomic, retain) NSNumber *created_at;
#property (nonatomic, retain) NSString *name;
- (void) initContext;
#end
#implementation Collect
#dynamic created_at;
#dynamic name;
- (void) initContext{
if (managedObjectContext == nil)
{
managedObjectContext = [MyAppDelegate managedObjectContext];
}
}
#end
And I use it by:
Collect *collect = [[Collect new] autorelease];
[collect initContext];
But when run it shows:CoreData: error: Failed to call designated initializer on NSManagedObject class 'Collect'.
I want to know How to add NSManagedObjectContext instance to NSManagedObject model correctly ?
You cannot add a managed object context to an managed object, it works the other way around: You need a managed object context first, and then you can create objects in this context.
See e.g. the NSManagedObjectContext documentation:
An instance of NSManagedObjectContext represents a single “object
space” or scratch pad in an application. Its primary responsibility is
to manage a collection of managed objects. These objects form a group
of related model objects that represent an internally consistent view
of one or more persistent stores. A single managed object instance exists in one and only one context, but multiple copies of an object
can exist in different contexts.
and the NSManagedObject documentation:
If you instantiate a managed object directly, you must call the designated initializer
(initWithEntity:insertIntoManagedObjectContext:).
There is also an utility method insertNewObjectForEntityForName:inManagedObjectContext: to create new objects. For example:
Collect *collect = [NSEntityDescription insertNewObjectForEntityForName:#"Collect"
inManagedObjectContext:[MyAppDelegate managedObjectContext]];
(You could put that into a class method of Collect if you like.)
And note that NSManagedObject already has a managedObjectContext method to get the context of the object:
NSManagedObjectContect *context = [collect managedObjectContext];
It is therefore not necessary (or might even cause problems) if you add an instance variable managedObjectContext to your managed object class.
I'm new with Core Data and there are some issues that I don't understand yet.
I have a entity called GCS (a subclass of NSManagedObject for Core Data):
#implementation GCS
#dynamic eye;
#dynamic ...
#dynamic ...
It works fine with Core Data when I do this:
GCS *failedBankDetails = [NSEntityDescription
insertNewObjectForEntityForName:#"GCS"
inManagedObjectContext:context];
failedBankDetails.eye = [NSNumber numberWithInt:12];
But then, in another class I have a property of GCS type:
#interface ModelManager : NSObject
{
GCS *tempGCS;
}
#property (nonatomic, retain) GCS *tempGCS;
...
In a method of ModelManager I tried this:
tempGCS.eye = [NSNumber numberWithInt:0];
But raised exceptions:
Failed to call designated initializer on NSManagedObject class 'GCS'
-[GCS setEye:]: unrecognized selector sent to instance 0x4d32ac0
Why cant I use the dot notation now? I think the #dynamic is the clue, but I shouldn't change it because I need to use it for Core Data, right?
Please help me and sorry for my english.
Thanks!
Dot notation has nothing to do with it, you'd get the same error if you called [tempGCS setEye:...]. The error is that you neglected to call initWithEntity:insertIntoManagedObjectContext: when creating the object in tempGCS; in particular, [[GCS alloc] init] will not work correctly.
I'm new to iOS and Objective-C and trying to create a class that has a generic property.
#interface HeaderInfo : NSObject {
NSString *label;
id value;
}
#property (nonatomic, retain) NSString *label;
#property (nonatomic, retain) id value;
- (HeaderInfo *)initWithLabel:(NSString *)lbl value:(id)val;
#end
Then I'm trying to add this class to an array:
[generalSection.items addObject:[[HeaderInfo alloc] initWithLabel:#"Tacho seal security" value:#"Some String Value"]];
[generalSection.items addObject:[[HeaderInfo alloc] initWithLabel:#"Tacho seal security" value:YES]];
but compiler doesn't like the 2nd addition and says:
Warning: passing argument 2 of 'initWithLabel:value:' makes pointer from integer without a cast
What I'm doing wrong? Any help is greatly appreciated.
And also how can check the value later on whether it's a BOOL or NSString?
Thanks.
The BOOL type is not a object, so you can't pass it as id (a generic object).
You should pass an NSNumber. An NSNumber is an object that encapsulate numbers when you want to pass a number as an object.
You can create a NSNumber like this : [NSNumber numberWithBool:YES];
You can retrieve the value with [value boolValue];
If you want to check the type of object you're having at runtime you can to it like that :
if ([value isKindOfClass:[NSNumber class]]) {
//It's a number
}
else if ([value isKindOfClass:[NSString class]]) {
//It's a string
}
the problem I am trying to solve in an application that is using Core Data is to be able to hold a calculated value in a NSManagedObject custom ivar. The calculated value that I want to store is in fact an image. I do not want to persist these images; I build them and destroy them throughout the lifetime of the application. I tried along the lines of:
#interface RTStaffImage : NSManagedObject {
UIImage *image;
}
// Custom properties
#property (nonatomic, retain) UIImage *image;
// Managed object properties
#property (nonatomic, retain) NSNumber *imageID;
#property (nonatomic, retain) NSString *imageName;
and custom accessors methods:
- (void)setImage (UIImage*)im;
- (UIImage *)image;
and in the implementation:
#implementation RTStaffImage
#synthesize image;
#dynamic imageID;
#dynamic imageName;
This fails at runtime with unrecognised selector problems:
-[NSManagedObject setImage:]: unrecognized selector sent to instance
The above approach is what Apple (or, at least as far as I see having read the docs) outlines for transient properties so it should work :-(
Any ideas, comments?
- (void)setImage (UIImage*)im;
you are missing a colon between setImage and (UIImage*). This is the correct version:
- (void)setImage:(UIImage*)im;
And where are the implementations of those two methods?
-[NSManagedObject setImage:]: unrecognized selector sent to instance
just curious, I read NSManagedObject there, are you sure you create an instance of RTStaffImage there?
Yeah, you have these backwards:
#synthesize image;
#dynamic imageID;
#dynamic imageName;
You're providing an implementation for setImage and image, so image should be #dynamic, and the others you need synthesized methods for, so use #synthesize for imageID and imageName.
Good point, they should all be #dynamic since you're with CoreData.
2nd attempt: you have set RTStaffImage as the Class name in the Entity, right?
3rd attempt: is RTStaffImage.m actually part of the Target being built?