NSManagedObject: isUpdated and isInserted - iphone

I keep track of my 'objects' using the isUpdated instance method of NSManagedObject Class.
When I'm modifying an exisiting object, it works.
If I create a new object using for example:
[NSEntityDescription insertNewObjectForEntityForName:#"Entity" inManagedObjectContext:managedObjectContext]
I can't use the isUpdated, I have to use the isInserted.
This works, but what I want to check, if the object has been modified with new data.
isInserted will return FALSE no matter if the object has been changed or not, it only take care if has been inserted or not ...
what can I use ? I can track the initial state of the object properties but I would prefer the isUpdated approach.
thanks!!!
r.

I'm not sure i completely understand your question, however, if you want to check whether your working with an unsaved new NSManagedObject, you can do that by writing a small category for NSManagedObject:
#interface NSManagedObject(Utility)
/**
Returns YES if this managed object is new and has not yet been saved in the persistent store.
*/
- (BOOL)isNew;
#end
#implementation NSManagedObject(Utility)
- (BOOL)isNew {
NSDictionary *vals = [self committedValuesForKeys:nil];
return [vals count] == 0;
}
#end
If you've created a new managed object using:
[NSEntityDescription insertNewObjectForEntityForName:#"Entity" inManagedObjectContext:managedObjectContext]
You can use the -isNew method to check whether it has been saved or not.

isInserted indicates if the object is "new" (newly inserted to NSManagedObjectContext). I think what You need is method hasChanges (it's on NSManagedObject and also on NSManagedObjectContext)...
BOOL someChangeHappendToObject = [myObject hasChanges];
checkout NSManagedObject hasChanges documentation

Related

Adding NSManagedObjects to a one-to-many relationship

I have a to-many relationship, e.g. A student has many classes.
Why is it when I run the following code _classes does NOT have the new Cls object in it? Yet when I close the app and reopen it does.
And as a follow up question, How would I get the new list of classes right after adding adding a new one?
NSMutableSet* classes = [student mutableSetValueForKey:#"classes"];
NSManagedObject* cls = [NSEntityDescription insertNewObjectForEntityForName:#"Cls" inManagedObjectContext:context];
[cls setValue:name forKey:#"name"];
[student addClassesObject:cls];
NSError* err;
[context save:&err];
NSMutableSet* _classes = [student mutableSetValueForKey:#"classes"];
And this is what my addClassesObject: operation looks like (auto generated by XCode)
- (void)addClassesObject:(Cls*)cls
{
}
Thank you!
You can't add objects to the set directly. You need to use Core Data generated accessors or your own custom ones. Look in your .h file and you should see something along the lines of
-(void)addClsObject:(Cls *)theObject;
And
-(void)addClsObjects:(NSSet *)set;
So for your particular case, you would do the following once you have your Cls object:
[student addClassesObject:cls];
Then perform you save and you should be able to retrieve the classes set. FYI, calling this method and the relatd NSSet relatd method also sets up the reverse relationship for you.
Good luck
T

Need some help understanding transient properties in Core Data

I read the documentation on transient properties but I can't really understand their purpose. Can someone tell me the difference between having and not having a transient property if I have a custom subclass of NSManagedObject like this?
#interface Board : NSManagedObject
{
NSMutableArray *_grid;
}
// Core Data to-many relationship
#property (nonatomic, retain) NSSet *pieces;
#property (nonatomic, readonly) NSArray *grid;
-(void)awake;
-(void)movePiece:(PieceState *)piece to_x:(int)x y:(int)y;
#end
#implementation Board
#dynamic pieces;
-(void)awakeFromInsert {
[super awakeFromInsert];
[self awake];
}
-(void)awakeFromFetch {
[super awakeFromFetch];
[self awake];
}
-(void)awake {
_grid = nil; // probably not necessary
}
-(NSArray *)grid {
if (!_grid) {
_grid = [[NSMutableArray alloc] initWithCapacity:10];
for (int i = 0; i < 10; i++) {
NSMutableArray *column = [[NSMutableArray alloc] initWithCapacity:10];
[_grid addObject:column];
for (int j = 0; j < 10; j++)
[column addObject:[NSNull null]];
[column release];
}
for (PieceState *piece in self.pieces)
if (piece.x >= 0 && piece.y >= 0)
[[_grid objectAtIndex:piece.x] replaceObjectAtIndex:piece.y withObject:piece];
}
return _grid;
}
-(void)movePiece:(PieceState *)piece to_x:(int)x y:(int)y {
if (x >= 0 && y >= 0) {
NSObject *capturedPieceObject = [[self.grid objectAtIndex:x] objectAtIndex:y];
if ([capturedPieceObject isKindOfClass:[PieceState class]]) {
PieceState *capturedPiece = (PieceState *)capturedPieceObject;
[self removePiecesObject:capturedPiece];
[[self managedObjectContext] deleteObject:capturedPiece];
capturedPiece = nil;
}
}
if (_grid) {
if (piece.x >= 0 && piece.y >= 0)
[[_grid objectAtIndex:piece.x] replaceObjectAtIndex:piece.y withObject:[NSNull null]];
if (x >= 0 && y >= 0)
[[_grid objectAtIndex:x] replaceObjectAtIndex:y withObject:piece];
}
[piece setX:x];
[piece setY:y];
}
- (void)didTurnIntoFault {
[_grid release];
_grid = nil;
[super didTurnIntoFault];
}
#end
So pieces and grid present two ways to access the same data. pieces is the actual Core Data relationship property, and is a dense list of all the pieces. grid is a way to find the contents of a particular space on the board addressed by (x, y) coordinates. grid is built lazily and updated (as long as it exists) when a piece changes location.
I'm not declaring grid as a transient property and everything is working fine. I'm just wondering if there is some unusual condition that could arise that would cause a bug if I don't declare a transient property.
I think I read transient properties are needed to get proper undo behavior if you're doing a derived property like this. I'm not using undo, and in any case I don't see how it could work in this case. If a piece move is undone, the undo manager can assign the old value of _grid back to it (maybe assuming I didn't make it readonly), but the old value is the same as the new value. It is a pointer to the same NSMutableArray instance, only the contents have changed. Anyway I don't use undo.
So do I get any benefit if I declare grid to be a transient property?
Additional question. What if I have code like this:
Board *board = someOtherManagedObject.board;
NSObject *boardContents = [[board.grid objectAtIndex:5] objectAtIndex:5];
Is it possible board is a fault after accessing someOtherManagedObject.board? I'm having trouble understanding faulting too. I think in that case my code would crash. I noticed awake sets _grid to nil. I think the sequence would be like this:
grid getter called
_grid allocated
self.pieces accessed
fault fires
awake called
_grid = nil
return to grid getter
[[_grid objectAtIndex:... access nil value, crash or at least no-op
grid getter returns nil
crash or incorrect behavior when boardContents is expected to contain a value
On the other hand, maybe if I declare grid to be a transient property, then the fault fires before my grid getter is called?
From TechZen:
Faults are placeholder objects that define an object graph with relationships but don't load attribute values. They will log as instances of either an NSManagedObject or of a private _NSFault... class.
Because unmodeled properties are only attributes of the custom NSManagedObject subclass and not the entity, the fault objects know nothing about them. Fault objects are initialized from the data model so that all the keys they respond to must be in the data model. This means faults will not reliably respond to request for unmodeled properties.
Wait what? I'm starting to realize my objects can be faults at any time but are you telling me they might not even be instances of my class!? Or if you use a custom subclass are they guaranteed to be the sort of faults that are instances of NSManagedObject (specifically my subclass)?
If they aren't instances of the custom class then what happens with something like this:
#interface Foo : NSManagedObject {
int data;
}
#property (nonatomic, retain) NSString *modeledProperty;
-(void)doSomething;
#end
#implementation Foo
#dynamic modeledProperty;
-(void)doSomething {
data++;
}
#end
What happens if I call doSomething on a fault?
Doesn't respond to selector, crash
Runs my code, but my instance variables don't exist, who knows what happens when it does data++
data exists, just modeledProperty doesn't exist because it's a fault
Transient properties fix this problem. The transient property provides a key that the context can observe without saving. If you have a fault, sending it a key-value message for a transient property will trigger the context to "fire" the fault and load the complete managed object.
Okay, but what if I have an instance method that's not a property accessor, like doSomething above? How do I make sure I have a real object before I call it? Or can I call it, and first thing in the method body make sure I have a real object (for example by accessing a modeled property)?
In your case, you want to use a transient property for grid if the value of grid depends on the values of any modeled properties of the Board class. That is the only way to guarantee that grid will always be populated when you access it.
I thought if it depended on the values of modeled properties, then it would fire the fault when it depended on them, i.e. the line for (PieceState *piece in self.pieces) fires the fault because it accesses self.pieces, which is a modeled property. But you are telling me which?
I can't even call the grid getter method on a fault
I can call it but I can't use _grid the way I want to
It seems if I understand what you're saying and it's true, the custom subclasses of NSManagedObject are very limited.
They can't have any instance methods that aren't modeled property getters or setters, because the object can't be guaranteed to exist in a useable state when they are called. (Exception: instance methods that are just helper methods for property accessors would be fine.)
They can't have any instance variables for any useful purpose other than temporary caches of computed values, because those instance variables could be erased at any moment. I know they won't be persisted on disk, but I thought they would at least be persisted as long as I retained the object in memory.
If that's the case then are you not intended to put application logic in your custom NSManagedObject subclasses? Should application logic reside in other classes that have references to the managed objects, and the managed objects are only dumb objects that you read from and write to (just a little bit smart, with some capabilities to maintain data consistency)? Is the only point of subclassing NSManagedObject to do some "tricks" with non-standard data types?
The advantage of transient properties comes from the difference between modeled/observed properties and unmodeled/unobserved properties.
The managed object context uses key-value observing (KVO) to monitor modeled properties. Based on the information provided in the data model, it knows what properties must have values, what default, minimum and max values are, when the property is changed and, most importantly, whether the managed object has a key name for a property. All this provides the "managed" part of managed objects.
Modeled properties do not require a custom NSManagedObject subclass but can use a generic NSManagedObject instance initialized to an entity. Accessing a modeled property of a fault (see below) causes the fault to load fully.
The managed object context doesn't observe unmodeled properties and unmodeled properties require a custom NSManagedObject subclass. The unmodeled properties are attributes of the class only and do not show up in the entity and they are never persisted in Core Data. Changes to unmodeled properties go unnoticed by the context.
Faults are placeholder objects that define an object graph with relationships but don't load attribute values. You can think of them as "ghost" objects. They will log as instances of either an NSManagedObject or of a private _NSFault... class. If it is a NSManagedObject the attributes are all empty. When a fault "fires" or is "faulted in" the placeholder object is replaced with a fully populated NSManagedObject instance whose attributes can be read.
Because unmodeled properties are only attributes of the custom NSManagedObject subclass and not the entity, the fault objects know nothing about them. Fault objects are initialized from the data model so that all the keys they respond to must be in the data model. This means faults will not reliably respond to request for unmodeled properties.
Transient properties fix this problem. The transient property provides a key that the context can observe without saving. If you have a fault, sending it a key-value message for a transient property will trigger the context to "fire" the fault and load the complete managed object.
It is important to note that although the data model has a key name for a transient property, the property only has a value when the managed object is fully instantiated and loaded. This means that when you do any fetches, which operate solely in the persistent store, the transient properties will have no values.
In your case, you want to use a transient property for grid if the value of grid depends on the values of any modeled properties of the Board class. That is the only way to guarantee force Core Data to guarantee that grid will always be populated when you access it.
[Edit:
That last is highly theoretical. Using a transient property ensures that Core Data tracks the property such that the accessing the property will cause a fault to fire and provide the data. However, in practice accessing any modeled property will reliably fire the fault and unmodeled methods are always available (see below.)
You can also use:
+[NSManagedObject contextShouldIgnoreUnmodeledPropertyChanges:]
… to force a context to watch unmodeled properties. However, that can cause unanticipated and unmanaged behavior if the unmodeled properties have side effects.
I think that it is good practice to use transient properties whenever possible to make sure everything is covered.]
Update:
Okay, but what if I have an instance method that's not a property
accessor, like doSomething above? How do I make sure I have a real
object before I call it?
I think you're over thinking this and my cumbersome explanation didn't help any.
Core Data manages all these issues for you. I've been using Core Data as long as there has been a Core Data and I have never run into any problems. Core Data wouldn't be much use if you had to constantly stop and check if the objects were faults or not.
For example, I set up a simple model with classes like so:
Alpha:
#class Beta;
#interface Alpha : NSManagedObject {
#private
}
#property (nonatomic, retain) NSNumber * num;
#property (nonatomic, retain) NSString * aString;
#property (nonatomic, retain) NSSet *betas;
-(NSString *) unmodeledMethod;
#end
#interface Alpha (CoreDataGeneratedAccessors)
- (void)addBetasObject:(Beta *)value;
- (void)removeBetasObject:(Beta *)value;
- (void)addBetas:(NSSet *)values;
- (void)removeBetas:(NSSet *)values;
#end
#implementation Alpha
#dynamic num;
#dynamic aString;
#dynamic betas;
-(NSString *) unmodeledMethod{
return #"Alpha class unmodeledMethod return value";
}
#end
Beta:
#class Alpha;
#interface Beta : NSManagedObject {
#private
}
#property (nonatomic, retain) NSNumber * num;
#property (nonatomic, retain) NSSet *alphas;
-(NSString *) unmodeledMethod;
-(NSString *) accessModeledProperty;
#end
#interface Beta (CoreDataGeneratedAccessors)
- (void)addAlphasObject:(Alpha *)value;
- (void)removeAlphasObject:(Alpha *)value;
- (void)addAlphas:(NSSet *)values;
- (void)removeAlphas:(NSSet *)values;
#end
#implementation Beta
#dynamic num;
#dynamic alphas;
-(NSString *) unmodeledMethod{
return [NSString stringWithFormat:#"%# isFault=%#", self, [self isFault] ? #"YES":#"NO"];
}
-(NSString *) accessModeledProperty{
return [NSString stringWithFormat:#"\n isFault =%# \n access numValue=%# \n isFault=%#", [self isFault] ? #"YES":#"NO", self.num,[self isFault] ? #"YES":#"NO"];
}
#end
Then I created an object graph of Alpha object with a related Beta object. Then I restarted the app and ran a fetch of all Alpha objects. Then I logged the following:
id aa=[fetchedObjects objectAtIndex:0];
id bb=[[aa valueForKey:#"betas"] anyObject];
NSLog(#"aa isFault= %#",[aa isFault] ? #"YES":#"NO");
//=> aa isFault= NO
NSLog(#"\naa = %#",aa);
//=> aa = <Alpha: 0x63431b0> (entity: Alpha; id: 0x6342780 <x-coredata://752A19D9-2177-45A9-9722-61A40973B1BC/Alpha/p1> ; data: {
//=> aString = "name 2";
//=> betas = (
//=> "0x63454c0 <x-coredata://752A19D9-2177-45A9-9722-61A40973B1BC/Beta/p7>"
//=> );
//=> // ignore fetchedProperty = "<relationship fault: 0x6153300 'fetchedProperty'>";
//=> num = 0;
//=> })
NSLog(#"\nbb isFault= %#",[bb isFault] ? #"YES":#"NO");
//=> bb isFault= YES
NSLog(#"\nany beta = %#",[[bb class] description]);
//=> any beta = Beta
NSLog(#"\n-[Beta unmodeledMethod] =\n \n %#",[bb unmodeledMethod]);
//=> -[Beta unmodeledMethod] =
//=> <Beta: 0x639de70> (entity: Beta; id: 0x639dbf0 <x-coredata://752A19D9-2177-45A9-9722-61A40973B1BC/Beta/p7> ; ...
//=>...data: <fault>) isFault=YES
NSLog(#"\n-[Beta accessModeledProperty] = \n %#",[bb accessModeledProperty]);
-[Beta accessModeledProperty] =
//=> isFault =NO
//=> access numValue=2
//=> isFault=YES
NSLog(#"\nbb = %#",bb);
//=>bb = <Beta: 0x6029a80> (entity: Beta; id: 0x6029460 <x-coredata://752A19D9-2177-45A9-9722-61A40973B1BC/Beta/p7> ; data: {
//=> alphas = "<relationship fault: 0x60290f0 'alphas'>";
//=> num = 2;
//=>})
Note that:
Both aa and bb are set to the expected class even though I did a generic object assignment. The context ensures that the fetch returns the proper class.
Even bb's class is Beta it reports as a fault meaning that the object represents an instance of the Beta class but that none of it's modeled properties are populated.
The bb object responds to the unmodeledMethod selector even though within the method it still reports as a fault.
Accessing the modeled property of Beta.num converts bb from a fault even before the call is made (the compiler sets it to trigger) but as soon as the access is done it reverts back to a fault.
The objects in the relationships are not only faults but not the same objects returned by accessing the relationship. In Alpha.betas the Beta object has the address of 0x63454c0 whereas bb has the address of 0x639de70> while it is a fault. After it converts from a fault and then back again, it's a address is 0x6029a80. However, the managedObjectID of all three objects is the same.
The morals here are:
"faults" are more about the state of a managed object and less about the actual class. Depending on how you access the object, you might get the actual subclass or you might get an instance of the hidden _NSFault… classes. From the coders perspective, all these different objects are interchangeable.
Even if a managed object reports as a fault, it will still respond to unmodeled selectors.
Accessing any modeled property causes the fault to fire and the object becomes fully active.
Core Data does a great deal of object swapping behind the scenes that you can't control and shouldn't worry about.
In short don't worry about unmodeled properties and methods. They should work transparently. It's best practice to use transient properties especially if those properties have side effects with modeled properties. You can force a context to track unmodeled properties but that can cause unnecessary complexity.
If you have doubts, just perform test yourself on faults to ensure that your class works.

objective c - Warning "Potential leak of an object" created with a class method

I am using XCode 4.0.2 for a iOS4 project.
I have this class method that construct an object. This is a constant that i need occasionally from start to end of the app.
However, running the Analyze tool this gives me a "Potential leak of an object" warning for the c object.
Should I be concerned? How can I fix it?
Thank you
You should read the Memory Management Programming Guide provided by Apple.
You should prefix your method name (+[XYZ A] in this instance) with new to make it clear that callers of your method know that they are responsible for releasing the object they receive. You would rename the method to +[XYZ newA].
If you do not wish to rename your method, you should at least return an autoreleased object, e.g. change the last line to return [c autorelease];
Every time you use that method, it creates a new instance of XYZ through the (deprecated) +new method.
If you want a single object of class XYZ that persists to the end of the app, you'll need to make some changes. The simplest way is to create this object on class initialization. In the .m file for whatever class we're looking at here, add the following:
static XYZ *instance = nil;
+ (void)initialize {
if (self != [ThisClass class])
return;
instance = [[XYZ alloc] init];
instance.X = ...;
instance.Y = ...;
instance.Z = ...;
}
And then, your A method:
+ (XYZ *)A {
return instance;
}

Core Data Wont Persist Property Updates to Database

I'm working with a subclass of NSManagedObject. Actually, it inherits from a class that inherits from a class that itself inherits from NSManagedObject (that shouldn't be a problem, right?).
The problem
After I make changes to the properties of the object, the object remembers the changes for its lifetime, but the changes are never saved to the database.
How Do I Know This?
I know this because:
when I restart the app, the changes I've made are lost.
telling the context to refresh the object – AFTER I've made changes to the object and told the context to save – sets the object's values back to their original state before I made the changes.
when running the app in the simulator, I can look at the sqlite database file in the Finder, and it's modified date isn't updated when I attempt to save the context.
Nothing is being written to the database!
Context
I'm using the auto-generated delegate methods to create the store coordinator and the context. Then I'm passing the context to the view controllers in their init methods, as recommended in the docs. The store is SQLite.
I am able to successfully insert objects into the database and read them. I can even make property changes to the newly inserted object and save it successfully. I simply don't seem to be able to update object properties when the object is pulled back out of the database.
The object is fetched from the store via a relationship from another object. After making changes to its properties, I call the context's save method. However, before doing so, I call the object's isUpdated method and the context's hasChanges method, and both return false. Shouldn't they return true since I've just made changes to the object's properties but haven't saved the context?
More
If I call the object's committedChanges method before saving the context, however, passing in the names of the properties that I've changed, I get back the correct values of the properties. I'm not sure what this means. I would have thought that this means that the object's new property values have been successfully saved, but clearly they are not saved.
I know that the result objects is registered with a context. If I call
[[result managedObjectContext] refreshObject:result mergeChanges:YES];
the object reverts back to the original property values. This means that the context is there and that it is the same context from which the record was fetched. And it means that the new property values are never written tot he database.
Some Code
Here's the code where I'm poking around with all of these things. There are other places in my code where I'm making property changes, but the changes are never saved.
- (IBAction)statusControlChanged:(UISegmentedControl *)control {
WCAAssessmentResult *result = [self currentResult];
/* printing the existing property values */
if (![result.complete boolValue]) NSLog(#"result is in progress!");
else if ([result.passed boolValue]) NSLog(#"result is passed!");
else NSLog(#"result is not passed!");
/* changing the property values */
switch (control.selectedSegmentIndex) {
case 0:
NSLog(#"setting incomplete");
result.complete = [NSNumber numberWithBool:NO];
break;
case 1:
NSLog(#"setting passed");
result.passed = [NSNumber numberWithBool:YES];
result.complete = [NSNumber numberWithBool:YES];
break;
case 2:
NSLog(#"setting failed");
result.passed = [NSNumber numberWithBool:NO];
result.complete = [NSNumber numberWithBool:YES];
break;
default:
break;
}
/* this method always returns an empty dictionary */
NSLog(#"%#", [result changedValues]);
/* this method returns the values that I just set */
NSLog(#"%#", [result committedValuesForKeys:[NSArray arrayWithObjects:#"complete", #"passed", nil]]);
/* isUpdated returns false */
if (![result isUpdated]) {
NSLog(#"result is not updated?! WTF!?!?");
}
/* hasChanges returns false */
if (![[result managedObjectContext] hasChanges]) {
NSLog(#"context has no changes!? WTF!?!?");
}
/* saving the context produces no error */
NSError *error = nil;
if (![[result managedObjectContext] save:&error]) {
NSLog(#"save failed");
NSLog(#"%#",[error description]);
}
}
A Twist
If I create a new result object by inserting a new record into the context, I can set that object's properties and they are saved successfully. In the above code, I'm fetching the object as a member of a to-many association from another object. Is that a clue?
I'm tearing my hair out over this. What the hell could be going wrong here?
What's NOT The Problem
I've logged the object's class, and it is indeed the correct class
I've made sure that the managedObjectContext I'm saving is the same as the object's context
I haven't made any changes to the auto-generated setter/getter methods of my managed object classes
I've tried using the setValue:forKey: method instead of object's properties
I've used the -com.apple.CoreData.SQLDebug 1 argument to log Core Data SQL, and no SQL is logged when I update and save the object's properties
I do not really understand your statement
WCAAssessmentResult *result = [self currentResult];
Indeed, if you are accessing a to-many relationship from an object, you should get back a set, not an object. Anyway, without seeing the code it's hard to tell. The problem you are experiencing may or may not lie there.
I would rather expect in your code something like the following snippet to access objects belonging to a to-many relationship. I assume that yourObject is the object you use to access the WCAAssessmentResult objects in the to-many relationship, which I call results.
NSMutableSet *resultObjects = [yourObject mutableSetValueForKey:#"results"];
NSPredicate *predicate = ...
[resultObjects filterUsingPredicate:predicate];
for(WCAAssessmentResult *result in resultObjects){
// modify as needed the current result object
}
NSError *error = nil;
if (![managedObjectContext save:&error]) {
NSLog(#"save failed");
NSLog(#"%#",[error description]);
}
Did you verify that the managedObjectContext you are using to save the object is valid (not nil) ?
Some ideas in no particular order:
I would log the class of the result object and make sure it is the class you think it is. Some confusion with super/sub classes could result in certain values not being saved.
If you made any alterations in the setter/getter methods in any class in the hierarchy, look closely at those methods especially if you used a primativeValue method. Simply leaving out willChangeValue and didChangeValue can cause changes to be invisible to the context and sometimes to the object itself.
I would log the context you are saving as well as managedObjectContext property of the result object. Confirm they are indeed the same context.
Skip using the property accessors (the dot notation) and use setValue:forKey and see if that makes any difference. If so, you have an accessor problem. Likewise, you could try setPrimativeValue:forKey to also check for an accessor problem.
If I had to bet, I would put my money on you assigning the objects returned by a fetch to the wrong class.

Retrieve properties of "id" type object iphone

I'm facing some difficulty in retrieving properties of "id" type object. This is how I'm accessing it:
I'm doing following to assign an object to id type object from a generic array containing different types of objects and calling method "savedata" to which I'm passing the object as well as its type:
for(id objInArray in genericArray){
NSString *objType = [objInArray valueForKey:#"type"];
[objInArray retain];
[self saveData:objInArray :objType];
}
In savedata method I'm writing following code to retrieve the properties of id object:
-(void)saveData:(id)object :(NSString *)objectType
{
self.managedObjectContext = appDelegate.managedObjectContext;
if([objectType isEqualToString:#"event"])
{
Event * newEvent = (Event *)[NSEntityDescription
insertNewObjectForEntityForName:#"Event"
inManagedObjectContext:self.managedObjectContext];
[newEvent setEletitle:[NSString stringWithFormat:#"%#", [object valueForKey:#"eletitle"]]];
[self saveAction];
}
But the object "object" containing the values fails to assign them to object newEvent.
I also tried to retrive this value in a string object like this:
NSString *eletit = [object valueForKey:#"eletitle"];
[eletit retain];
But eletit is also invalid at the end of this transaction.
Can anybody please help? This' really urgent.
Thanx in advance.
I don't have you answer unfortunately but I have few comments on your code.
Are you sure it's normal you array contain so generics object? It's strange because all your object contained in your array need to respond to "type" or "eletitle" messages, so I guess objInArray is less generic than just "id".
Second, it's not recommended to have selector like saveData::, in Objective-C it's usual and recommended to name the arguments, it's more understandable.