NSNumber assignment issues. Wrong number being assigned - ios

I'm receiving data in JSON from an API and after converting the data into custom class I'm attempting to write certain properties into a core-data db.
My code is:
NSLog(#"topPost: %#; post(in): %#", topPostsEntity.totalAgainst,post.totalAgainst);
topPostsEntity.totalAgainst = post.totalAgainst;
NSLog(#"topPost: %#; post(in): %#", topPostsEntity.totalAgainst,post.totalAgainst);
topPostEntity is a Core-Data entity.
topPostEntity.totalAgainst is defined as follows:
#property (nonatomic, retain) NSNumber * totalAgainst;
Nothing special in the getter:
- (NSNumber *)totalAgainst
{
if (!_totalAgainst) _totalAgainst = [[NSNumber alloc]init];
return _totalAgainst;
}
post.totalAgainst is also defined as an NSNumber as follows:
#property (nonatomic,strong) NSNumber *totalAgainst;
To my shock this is what the log reads:
2013-11-02 00:42:42.476 kello[6260:70b] topPost: 0; post(in): 40000
2013-11-02 00:42:42.476 kello[6260:70b] topPost: -25536; post(in): 40000
How does assigning 40000 to topPostEntity.totalAgainst make it store -25536?

Solved the problem.
I had set the core-data entity to Integer 16. I changed this to Integer 64 and that resolved the problem. I'm not sure how anyone's going to find this q to help their problem, but if so - cheers.

Related

convert NSString to int16_t and insert them inside core data

hello what i am trying to do is to taking a NSString value from UITextField and convert this value into int16_t to save it inside my core data after many hour of googling some of the stack people said that core data could not accept primitive data type such as int Boolean etc... and should receive object type such as NSNumber NSInteger etc... here is my code:
CoreData *coreDat = [CoreData defaultStack];
numberEntity *entry = [NSEntityDescription insertNewObjectForEntityForName:#"NumberEntity" inManagedObjectContext:coreDat.managedObjectContext]
;
[entry setNumber:(NSNumber *)self.numberTextField.text];
and here is the entity class:
numberEntity.m
#import "numberEntity.h"
#implementation numberEntity
#dynamic number;
#end
numberEntity.h
#import <Foundation/Foundation.h>
#interface numberEntity : NSObject
#property (nonatomic,strong) NSNumber *number;
#end
and for my core data is integer 16
i could not post the image due to my low reputation i am so sorry also i am still new to stackoverflow.com
but after running this code i got this exception :
Unacceptable type of value for attribute: property = "number"; desired type = NSNumber; given type = __NSCFString; value = 1.
hope you will help me forget to mention that i am still newbie in IOS development and i came from android development
Thanks in advance
Just replace this line [entry setNumber:(NSNumber *)self.numberTextField.text]; to [entry setNumber:#([self.numberTextField.text intValue])]; .Hope its working.

What does "[self data][date]" mean?

Can any one just tell me what the below code in iOS mean? Its a piece of code from MBCalendarKit.
#property (nonatomic, strong) NSMutableDictionary *data;
- (NSArray *)calendarView:(CKCalendarView *)calendarView eventsForDate:(NSDate *)date
{
return [self data][date];
}
How does the above function return an NSArray when the global data is an NSMutableDictionary and the local date is NSDate?
And what does [self data][date] mean?
If data is an NSDictionary then it means exactly the same thing as [data objectForKey:date]. That syntax was introduced a couple of years ago — ideally read the whole thing but if in a hurry then jump to 'Object Subscripting'.

Fetch objects in Core Data through one to many relationship

I have this One-to-Many relationship in Core Data:
Each SBQChrono can have many SBQLaps.
In my model I have the class SBQLap:
#interface CILap : NSObject
#property (strong, nonatomic) NSDate * lapDate;
#end
And the class SBQChrono:
#interface CIChrono : NSObject
#property (strong, nonatomic) NSDate * startDate;
#property (strong, nonatomic) NSDate * stopDate;
#property (strong, nonatomic) NSOrderedSet *laps;
#end
I get all the SBQChrono entities doing:
NSFetchRequest *request=[[NSFetchRequest alloc] initWithEntityName:kChronoEntityName];
NSError *error;
NSArray *objects = [appContext.managedObjectContext executeFetchRequest:request error:&error];
How can I get the specified SBQLap entitys per each SBQChrono I find? Ive read a lot of posts and cant get the solution.
UPDATE:
After trying to cast the NSManagedObject, I realized that the laps is returned as nil value.
Doing:
for (NSManagedObject *oneObject in objects) {
CIChrono *chrono=(CIChrono *)oneObject;
NSLog(#"startDate %#", chrono.startDate);
NSLog(#"stopDate %#", chrono.stopDate);
NSLog(#"laps %#",chrono.laps);
}
I get the message:
2014-01-28 14:39:48.379 Chrono[2341:70b] startDate 2014-01-28 12:27:53 +0000
2014-01-28 14:39:48.380 Chrono[2341:70b] stopDate 2014-01-28 12:27:54 +0000
2014-01-28 14:39:48.380 Chrono[2341:70b] -[NSManagedObject laps]: unrecognized selector sent to instance 0x8b959b0
2014-01-28 14:39:48.383 Chrono[2341:70b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSManagedObject laps]: unrecognized selector sent to instance 0x8b959b0'
Thanks
Lots of interesting answers on this one.
The answer is very simple and does not require subclassing NSManagedObject to access the objects in a relationship. You just need to use KVC (Key Value Coding) to access those objects. This is true of relationships and attributes.
If you want to use synthesized methods you can by subclassing as some have hinted at but that is not necessary.
Here is an extension to your example that you posted in your question:
for (NSManagedObject *oneObject in objects) {
CIChrono *chrono=(CIChrono *)oneObject;
NSLog(#"startDate %#", [chrono valueForKey:#"startDate");
NSLog(#"stopDate %#", [chrono valueForKey:#"stopDate"]);
NSLog(#"laps %#", [chrono valueForKey:#"laps"]);
NSSet *laps = [chrono valueForKey:#"laps"];
for (NSManagedObject *lap in laps) {
NSLog(#"Lap entity: %#", lap);
}
}
Note the -valueForKey: calls. Those are Key Value Coding which NSManagedObject instances (and all other Objective-C objects) respond to. I would suggest reading the documentation on KVC and KVO.
Each SQBChrono object contains a set of SBQLap objects that are associated with it. Look at your SQBChrono properties
#property (strong, nonatomic) NSOrderedSet *laps;
laps is a property that contains the many SBQLap objects to one SQBChrono object.
You can get an array from the set like this:
NSFetchRequest *request=[[NSFetchRequest alloc] initWithEntityName:kChronoEntityName];
NSError *error;
NSArray *chronoObjectArray = [appContext.managedObjectContext executeFetchRequest:request error:&error];
for (SQBChrono * chrono in chronoObjectArray) {
NSArray *lapsArray = [chrono.laps array];
NSLog("Chrono: %# laps: %#", chrono.startDate, lapsArray);
}
As you've added the SBQChrono objects to an array you will need to cast it:
SQBChrono *anObject = (SQBChrono *)objects[0];
Then you can:
anObject.laps;
Will give you the NSSet of all associated objects ?
Your array objects contains all your SBQChrono objects.
You can get all the SBQLaps associated with one chrono by doing:
SQBChrono * myChrono = objects[indexOfTheDesiredChrono];
The laps of the chrono are then in myChrono.laps, which is a NSOrderedSet (collection) of SBQLaps. Can be turn into an array like this :
NSArray * myChronoLaps = [myChrono.laps array]
You can fetch objects which have a relationship to 'SBQChrono'.
This can be done with two fetch requests, first fetch all the 'SBQChrono' objects & then perform a second request for 'SBQLap' entities with a predicate:
[NSPredicate predicateWithFormat:#"chrono IN %#",objects]
Looking at the model screenshot and code that you posted, it appears that the model has the relationship name set as lap (singular) but your class definition is using laps (plural). Core Data would be implementing an accessor for lap, but doesn't understand laps since it doesn't match the name in the model. Changing the model to say laps should fix that problem.

Core Data: setPrimitiveValue:forKey: behaves really weirdly

This is a mystery:
I'm invoking setPrimitiveValue:forKey: on an NSManagedObject. The key is a legit, persistent, modeled attribute of the object. However, setPrimitiveValue:forKey: fails, often setting the value for a different, arbitrary attribute. The docs say this behavior is expected when invoking setPrimitiveValue:forKey: for an unmodeled key. So it seems Core Data thinks the key is unmodeled.
The strange part:
When the key is hardcoded as a string literal, the primitive value is indeed set successfully. It only fails when the key is a variable. The variable I'm using happens to be passed from the keyPath argument of observeValueForKeyPath:ofObject:change:context:
The keyPath variable is the same as the string literal. isEqual: returns true and the hash values are equal. The keyPath variable is of type __NSCFString. Does anyone know why setPrimitiveValue:forKey: would behave any differently? (This behavior is on OS X 10.9.1)
An update with better information:
The misbehaving key traced back to a string loaded from a file on disk. The example below is an isolated case. If the attribute string "mainAttr" is written to disk and read back in, then setPrimitiveValue:forKey: sets the value for the wrong attribute, not "mainAttr".
Core data object:
#interface Boo : NSManagedObject
#property (nonatomic, retain) NSNumber * mainAttr;
#property (nonatomic, retain) NSNumber * attr1;
#property (nonatomic, retain) NSNumber * attr2;
#property (nonatomic, retain) NSNumber * attr3;
#end
-
#import "Boo.h"
int main(int argc, const char * argv[]) {
#autoreleasepool {
NSManagedObjectContext *context = managedObjectContext();
NSString *key = #"mainAttr";
// write to disk, read back in
NSString *path = [#"~/Desktop/test.txt" stringByExpandingTildeInPath];
[key writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:NULL];
key = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
Boo *boo = [NSEntityDescription insertNewObjectForEntityForName:#"Boo" inManagedObjectContext:context];
[boo setPrimitiveValue:#(5) forKey:key];
NSLog(#"Boo: %#", boo);
}
return 0;
}
You need the below 3 statements to set the value. Try it.
[self willChangeValueForKey:key];
[boo setPrimitiveValue:#(5) forKey:key];
[self didChangeValueForKey:key];

NSMutableArray removeObjectAtIndex causing unexpected SIGABRT

I have looked at numerous posts which state various ways in which to remove an object from an array correctly, but I am not sure which method is best to use in my instance. I am loading a dictionary from a plist, this dictionary contains numerous arrays, and these arrays contain another dictionary. So I have 3 storage devices setup, 1 to hold the overall dictionary, another for an array, and finally a dictionary to hold the object from the array:
Header:
NSMutableDictionary *questionsDictionary;
NSMutableArray *questionsArray;
NSDictionary *currentQuestion;
#property (nonatomic, retain) NSMutableDictionary *questionsDictionary;
#property (nonatomic, retain) NSMutableArray *questionsArray;
#property (nonatomic, retain) NSDictionary *currentQuestion;
So my first question is to do with the above, are (nonatomic, retain) the right things to use for the following code.
Next I load in my dictionary from the plist:
.m:
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathComponent:#"MultipleChoice.plist"];
self.questionsDictionary = [[NSDictionary dictionaryWithContentsOfFile:finalPath] retain];
I then setup my question array based upon type based upon my question type:
- (void)setupQuestionType : (NSString *)qType
{
if ([self.questionsDictionary objectForKey:qType])
{
self.questionsArray = [self.questionsDictionary objectForKey:qType];
[self pickRandomQuestion];
}
}
Finally (this is where I get the error), I want to grab the a question at random from this question category:
// Pick a random question number based upon amount of questions
int randomQuestionNum = [[NSNumber numberWithInt:(arc4random() % [self.questionsArray count])] intValue];
// Grab the dictionary entry for that question
currentQuestion = [self.questionsArray objectAtIndex:randomQuestionNum];
// Remove the question from the available questions
[self.questionsArray removeObjectAtIndex:randomQuestionNum]; (Error here)
// Set the question text
self.question.text = [currentQuestion objectForKey:kQuestionkey];
Now if I comment out the removeObjectAtIndex line then the code runs fine, and my question is displayed on the screen. This leads me to believe that it isn't a null pointer. So the logical answer points to the fact that self.questionsArray isn't a NSMutableArray. So I tried the following when setting the array:
- (void)setupQuestionType : (NSString *)qType
{
if ([self.questionsDictionary objectForKey:qType])
{
NSMutableArray *temp = (NSMutableArray *)[self.questionsDictionary objectForKey:qType];
self.questionsArray = (NSMutableArray *)temp;
[self pickRandomQuestion];
}
}
Purely to see if I could type_cast it but the error still occurs. Can anyone shed some light on what I'm doing wrong, or the best approach to take?
Don't typecast NSArray to NSMutableArray. Instead:
NSArray *temp = [self.questionsDictionary objectForKey:qType];
self.questionsArray = [NSMutableArray arrayWithArray:temp];
// code not tested.

Resources