CoreData entity's are not being correctly initialised - ios

im having a hard time with what it seems a very simple task. Im trying to create an entity (LVUser) and calling a custom method implemented in the class previously mentioned. Every attempt i made returns me an unrecognised selector sent to instance error. Im using MagicalRecord in my project but also tried with CoreData raw methods without luck anyway.
First Attempt
LVUser* user = [LVUser MR_createEntity];
[user signInWithDelegete:self];
Second Attempt
LVUser* user = [LVUser MR_createInContext:[RKObjectManager sharedManager].managedObjectStore.mainQueueManagedObjectContext];
[user signInWithDelegete:self];
Third Attempt
LVUser* user = [[NSManagedObject alloc] initWithEntity: [LVUser MR_entityDescription] insertIntoManagedObjectContext:[RKObjectManager sharedManager].managedObjectStore.mainQueueManagedObjectContext];
[user signInWithDelegete:self];
The last example gives me this warning
Incompatible pointer types initializing 'LVUser *' with an expression of type 'NSManagedObject *'
I don't get what i'm doing wrong, they are compatible pointer types indeed.
I tried deleting Xcode Derived Data and clean & build.

Related

What type of object is returned from ObjectForID

I am trying to retrieve an object from the managed object context and edit a value or two after it has been backed up to the cloud. In particular, I want to save an id provided by the cloud server.
To get the object, I'm trying to retrieve it using its managedObjectID.
I have tried:
Contacts *object = [_managedObjectContext objectWithID:_moID];
and
Contacts *object = [self.managedObjectContext objectRegisteredForID:_moID];
where moID is the managedObject id.
I then follow this up with
object.cid = #99; //ie I set it equal to some number
In both cases, although Contacts is an NSManagedObject class, it throws a yellow warning:
'Incompatible point types initializing contacts with an expression of type NSManagedObject'.
If Instead of calling it Contacts *object, I call it NSManagedObject *object, it no longer throws the warning but then will not allow me to say object.cid as it no longer knows what a cid is. In this case it throws red error:
Property cid not found on object of type NSManagedObject.
Can anyone suggest proper object type. Thanks in advance for any suggestions.
By looking at the method definition, you'll see that returned instance type is just NSManagedObject * as the warning said. What you need to do is just to cast the type appropriately:
Contacts *object = (Contacts *)[_managedObjectContext objectWithID:_moID];
and
Contacts *object = (Contacts *)[self.managedObjectContext objectRegisteredForID:_moID];
Note, your Contacts suppose to be a subclass of NSManagedObject.

Parse Error invalid type for key fromUser, expected map, but got *User

I have a parse class called User, another one called activity. An activity has a fromUser field that expects an Object.
When i make a new activity, when saving i get the error
invalid type for key fromUser, expected map, but got *User
The code im using is:
Activity *activity = [Activity object];
User *loggedInUser = [SessionService instance].loggedInUser;
[activity setFromUser:loggedInUser];
The other solutions on stackoverflow use pointers but i want to use an object so i want to get this working or atleast understand why it doesnt like my user object.
At first i thought it was my user object so i also tried:
PFObject *userObject = [PFObject objectWithClassName:#"User"];
userObject[#"name"] = loggedInUser.name;
[activity setObject:userObject forKey:#"fromUser"];
but i still get the same error so i know its not the my mapping of my user object to a class.
An object in mapping is a dictionary, in my case, i need to use a pointer to the object in the database.

NSError object already populated on first method call

I am following the book Test-Driven iOS development by G. Lee and came across this unit test, which I don't understand. First of all, if you need more code, please let me know right away.
-(void)testDelegateNotifiedOfErrorWhenNewsBuilderFails
{
MockNewsBuilder *builder = [MockNewsBuilder new];
builder.arrayToReturn = nil;
builder.errorToSet = underlyingError;
newsManager.newsBuilder = builder;
[newsManager receivedNewsJSON:#"Fake Json"];
...
}
-(void)receivedNewsJSON:(NSString *)objectNotation
{
NSError *error = nil;
// As you see error is nil and I am passing in a nil error.
NSArray *news = [_newsBuilder newsFromJSON:objectNotation error:&error];
...
}
#implementation MockNewsBuilder
-(NSArray *)newsFromJSON:(NSString *)objectNotation error:(NSError **)error
{
// But once I arrive here, error is no longer nil.
// (NSError **) error = 0x00007fff5cb887f0 domain: #"Fake Json" - code: 0
...
}
How is error auto-magically set?
UPDATE:
Thanks everyone for active discussion and advice. The answers explain how the caller side gets the error instance because of &, I understand that clearly. My question remains though why the callee side is pointing to a populated NSError instance, even though it had to be nil. I didn't set the error instance within newsFromJSON:error: so how is it already populated there?
I just changed [newsManager receivedNewsJSON:#"Fake Json1"]; and the error instance within newsFromJSON:error: reflects right away
(NSError **) error = 0x00007fff5b9b27f0 domain: #"Fake Json1" - code: 0. Its very confusing...
This is just pointer to pointer concept. You are passing the reference to the reference error object &error to the method -(NSArray *)newsFromJSON:(NSString *)objectNotation error:(NSError **)error;
And this will update the error object at the memory pointer you have passed.
See this is the concept of pointer to pointer.
Update:
Your error object is nil, yes its right. But you are not passing that error object to the newsFromJSON method, but the memory address of the error object( &error). That is the memory address of the error object.
This why you are getting non null value there inside your newsFromJSON method.
And one more thing, you can access the original object in your newsFromJSON method using the content of operator(* operator)
like **error = something;
This will update your original object ( NSError *error ) you declared in your caller method.
In C or CPP or Objective-C, & is the Address of operator and * is the content of operator.
&obj -> give the memory address of the obj
*obj -> give the content of the memory address in the obj.
** is a pointer to a pointer.
It means you need to pass a pointer address to a function or method.
Objective-C is a strict superset of C.
That means as in C functions and methods can only return one value.
There are two ways about it.
One is to wrap all your returns in structs or NSDictionaries or other collections.
This way is called an outParameter
It's passing a pointer address in.
C is a by copy language. But pointers are portable black holes that allow you to do wild things in C.
Objective-C and C++ give you the same wildness.
The error is set by Apple's framework code.
The Cocoa pattern is usually to return a BOOL and pass in an NSError pointer address.
If BOOL is NO check the NSError.
Apple framework will have put some presents in your NSError pointer address box.
Sometimes they don't use BOOL and instead return an object or nil.
Core Foundation C frameworks work very similarly and use in and out parameters a lot.
error is a variable of type NSError*, that is "pointer to NSError" (in objective-C, all objects are handled as references, as opposed to e.g. C++).
What this means is that error is a (local) variable that stores the address of the actual NSError object, initially nil.
The method you call creates an (autoreleased) NSError instance. In order to get a reference to that instance back, you need to pass the method the address of the pointer, or &error, which is, in turn, of type "pointer to pointer to NSError" (note the two-level indirection).
You do this because arguments to functions in C and methods in Objective-C are passed by value: if you just passed error, the value stored there (nil) alone is copied, and no matter what the called method does, the contents of the variable error on your side (the caller) can't be modified. To achieve this, you need to pass the address of error, or &error.
This way, the called method can "change" the contents of error (the address held there) so that it points to the newly created, NSError instance.
Does it make sense?
ADDENDUM: This is a very common pattern very often seen in Cocoa: The method being called could potentially fail, and instead of just using the return value to signal success/failure, and additional 'in/out' parameter is passed to retrieve detailed error information in case of failure. On failure, the method can return false (NO, 0, etc.), but in addition in can provide a more detailed error report (e.g. the reason for failure) inside the NSError instance.
EDITED: As #Droppy said, and seeing that all code involved is your own (i.e., not some first or third party framework), it is impossible that error is set to anything other than nil unless you explicitly allocate it somewhere. Perhaps you should "watch" it in the debugger to see when/where it is set. since the message seems to be set to #"Fake JSON", the first thing you could do is search that string in your project (all files).

Need help understanding a conditional crash when accessing my NSDictionary

I am keeping my data in a property called practiceRecords (an NSArray of dictionaries).
I check to see if the data already exists in the documents folder.
If yes, I load the data into self.practiceRecords.
If not, I build the array of dictionaries (using literal syntax), keeping this data in the self.practiceRecords property, and then write the data out to the documents folder.
(I am NOT reloading the data after writing it out)
As far as I am able to tell, there are no problems occurring during this process.
Then I have a step where I modify my data as follows ...
-(void)incNumberOfTriesFor:(NSString *)stringOfIndex {
if (self.practiceRecords)
{
int index = [stringOfIndex intValue];
int numberOfTries = [(NSNumber *)(self.practiceRecords[index][#"tries"]) intValue] + 1;
//CRASHING on this next line.
self.practiceRecords[index][#"tries"] = #(numberOfTries);
//message to helper method
[self writePracticeRecords];
}
}
So the first time through (when the array is built and written out) I get a crash at the indicated line.
The error is:
-[__NSDictionaryI setObject:forKeyedSubscript:]: unrecognized selector sent to instance
I quit the app, check the documents folder and see the data file written out with no issues.
I re-run the app, and then get no crash and the data file still looks great.
This is repeatable.
If the data file exists, no crash.
If the data first needs to be created, then a crash.
(In all cases, I manually look inside the resulting data file and see exactly what I expect to see - no issues there)
I'm not sure where to even begin squashing this bug, and would really like to understand the details of why this is happening.
Thanks very much for any help!
Just to recap the correct comments above:
-[__NSDictionaryI setObject:forKeyedSubscript:]: unrecognized selector sent to instance
NSDictionary does not implement any of the set... methods because it is immutable. You state that you're creating with literals syntax when the data is not found on disk. The literal syntax creates immutable containers
Instead, try...
// try to initialize from disk, but if not
// we can still use literal (immutable) syntax, but in a mutable container
self.practiceRecords = [NSMutableDictionary
dictionaryWithDictionary:#{ #"key" : #"value" }];

Saving custom class into Coredata

Hi i have used attribute type transformable and i have followed the procedure of archiving in one of the Forum .
But it says
CoreData: warning: no NSValueTransformer with class name 'SurveyResults' was found for attribute 'survey' on entity 'SurveyData'
2013-04-30 09:44:16.022 TestReachability[11641:c07] -[SurveyApplication encodeWithCoder:]: unrecognized selector sent to instance 0x845cb00
2013-04-30 09:44:16.023 TestReachability[11641:c07] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SurveyApplication encodeWithCoder:]: unrecognized selector sent to instance 0x845cb00'
Here is my code
SurveyApplication *survey =[[SurveyApplication alloc]init];
survey.name=#"dheeraj";
survey.phone=#"573-356-2598";
NSManagedObject *aStory = [NSEntityDescription insertNewObjectForEntityForName:#"SurveyData"inManagedObjectContext:self.managedObjectContext];
[aStory setValue:survey forKey:#"survey"];
NSError *saveError = [[NSError alloc]init];
if (![self.managedObjectContext save:&saveError]) {
NSLog(#"%#",saveError);
}
SurveyAppplication object is my custom class and im trying to create an object and then store it core data .Could you please help me out.
Thanks
Dheeraj
It's not enough to make the attribute transformable, you also need to arrange for the transformation to happen. You can't just tell Core Data to transform any old object and expect it to know what to do. You have a couple of options:
Don't tell Core Data how to transform the data. In this case, Core Data will attempt to call encodeWithCoder: on your object to convert it to NSData. That's why you get the error that mentions this method-- it's trying to call the method on your class, but that method doesn't exist. In this case your class must conform to NSCoding for the transformation to occur.
Tell Core Data how to transform the data. In this case you create a subclass of NSValueTransformer that performs the transformation. You configure this on the attribute, either in the Core Data model editor or in code. In this case, you must have a custom transformer class that knows how to perform the transformation.

Resources