Invalid operations to binary expression ('id' and 'id') - objective-c

I have a array fetched from the core data and trying to do some simple calculation but getting errors of Invalid operations to binary expression
pop_cum[i]= (pop_ln_array[i-1] + pop_ln_array[i]);
//getting error at this point of "Invalid operations to binary expression('id' and 'id')
I know we have to change the type of the array values into int but how?
NSManagedObjectContext *moc = [self managedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"Input_Details" inManagedObjectContext:moc];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];
// Set example predicate and sort orderings...
request.propertiesToFetch = #[ #"pop_Ln" ];
request.resultType = NSDictionaryResultType;
//if you change the sort order here, please change it to SDInputDetailsList also
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey:#"sewer_No" ascending:YES];
[request setSortDescriptors:#[sortDescriptor]];
NSError *error;
NSArray *pop_ln_array = [moc executeFetchRequest:request error:&error];
int arrayCount=[pop_ln_array count];
//Calculating cumulative population, flow & peak factor
NSLog(#"arrayCount is %d",arrayCount);
if (pop_ln_array == nil)
{
NSLog(#"Cumilative population line array is nil");
}
else
{
NSArray *pop_cum[arrayCount];
for(int i=0;i<[pop_ln_array count];i++)
{
NSLog(#"Cumilative array at %d is %#",i,pop_ln_array[i]);
if (i==0)
{
pop_cum[i]=pop_ln_array[i] ;
}
else
{
pop_cum[i]= (pop_cum[i-1] + pop_ln_array[i]); //getting error at this point of "Invalid operations to binary expression('id' and 'id')
}
}
}

Use as follows
for(int i=0;i<[pop_ln_array count];i++){
NSLog(#"Cumilative array at %d is %#",i,pop_ln_array[i]);
if (i==0){
pop_cum[i]=pop_ln_array[i];
NSLog(#"pop_cum[%d] %#",i,pop_cum[i]);
}
else {
NSLog(#"Pop_cum %#",pop_cum[i-1]);
[pop_ln_array[i]intValue]);
NSInteger first=[pop_ln_array[i-1]intValue], second=[pop_ln_array[i]intValue];
NSInteger sum=first+second;
pop_cum[i]=[NSString stringWithFormat:#"%d",sum];
}
}
You are adding two ids. Which can not be.
Convert it to integerValue or intValue or any numerical and then add.

Related

Boolean values and core data

I have Boolean values in a entity, the values are all show 0.
The values are fetched and no matter what I always get back a TRUE value.
Here is the code, the problem is probably at the last 2 lines of code.
What am I doing wrong?
-(NSInteger)getStatus:(NSString*)nameID;
{
**//Fetch Request**
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity =
[NSEntityDescription entityForName:#"status"
inManagedObjectContext:[self managedObjectContext]];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate
predicateWithFormat:#"id_Name = %#", nameID];
[fetchRequest setPredicate:predicate];
NSError *error = nil;
NSArray *fetchedObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
}
**//Values**
status *ENT_status;
ENT_status = [fetchedObjects objectAtIndex:0];
//Either way, both these lines return YES when it would be NO
//------------------------------------------------------------------
BOOL one = ENT_status.status_one;
NSNumber *two = [NSNumber numberWithBool:ENT_status.status_two];
By default, boolean values are represented as NSNumber objects in the managed objects.
So you can either use it as it is:
NSNumber *one = ENT_status.status_one;
or convert it to a plain (scalar) BOOL:
BOOL one = [ENT_status.status_one boolValue];
(In your code, the pointer ENT_status.status_one is always interpreted as YES.)
Alternatively, you can use the option "Use scalar properties for primitive data types"
when creating the managed object subclass in Xcode.
I know its a bit late and probably no one is using Objective-C anymore but i came across this problem and what worked for me was:
to retrieve a boolean value from object:
BOOL myBool = [[myManagedObject valueForKey:#"myKey"] boolValue];
and to set the new value:
myManagedObject.myKey = #YES;

Unable to sort NSMutableArray of Custom Objects

I've got an issue trying to sort an array of custom objects. It's looking as if my arrays aren't even hitting the sorting code, but rather simply just returning the array itself.
I have the following setup:
SearchResult : NSObject
--
Document : SearchResult
Tag : SearchResult
Folder : SearchResult
My code is getting returns as SearchResults then trying to compare them all with a key, name that is defined in the SearchResult implementation.
-(void) parseFolderContents:(NSDictionary *) data
{
NSMutableArray *searchResults = [[NSMutableArray alloc] init];
NSMutableArray *documents = [[NSMutableArray alloc] init];
NSMutableArray *folders = [[NSMutableArray alloc] init];
NSMutableArray *tags = [[NSMutableArray alloc] init];
NSArray *results = [data objectForKey:#"items"];
for (int i = 0; i < [results count]; i++)
{
SearchResult *result = (SearchResult *)[KTParser parseSearchResult:[results objectAtIndex:i]];
if ([result.type isEqualToString:#"document"]){
[documents addObject:result];
}
else if ([result.type isEqualToString:#"folder"])
{
[folders addObject:result];
}
else if ([result.type isEqualToString:#"tag"])
{
[tags addObject:result];
}
}
if ([documents count] > 0)
[searchResults addObject:documents];
if ([folders count] > 0)
[searchResults addObject:folders];
if ([tags count] > 0)
[searchResults addObject:tags];
....
So that's the code used to populate the array, which isn't anything special. I have tried each of these ways to compare the array. None have worked. Does anyone know where I'm going wrong?
First attempt:
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name"
ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedResults;
sortedResults = [searchResults sortedArrayUsingDescriptors:sortDescriptors];
Second attempt:
NSArray *sortedResults;
sortedResults = [searchResults sortedArrayUsingSelector:#selector(compare:)];
(implementing custom compare method on SearchResult/Document.m)
- (NSComparisonResult)compare:(SearchResult *)otherResult{
return [self.name compare:otherResult.name];
}
Third attempt:
sortedResults = (NSMutableArray *)[searchResults sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES selector:#selector(caseInsensitiveCompare:)]]];
Fourth attempt I tried using a block. I even tried putting code in to manipulate the sorting of it, which didn't work either. The array returned was exactly the same as the original:
sortedArray = [searchResults sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
if ([(SearchResult *)a itemId] < 20000 )
return NSOrderedAscending;
else
return NSOrderedDescending;
}];
Anyone have any ideas?
Found out the issue - I was adding arrays as objects instead of adding each object into the array. This was then calling sort on NSArray, instead of my custom objects. Changing the above code from [searchResults addObject:documents]; to [searchResults addObjectsFromArray:documents]; solved the issue!

Multiple fetch requests with complex predicates

I have a couple of views which present data from a CoreData entity in my app. To retrieve the data required for the views I often have to implement multiple fetchRequests which feels wrong - perhaps I'm still making basic mistakes like thinking of CoreData in too much of a SQL database sense.
In fact for one of my views I have 22 fetch requests which may well be the correct way of achieving what I need but as an iPhone/Objective-C novice I can't help questioning my approach. Here is a snippet of my code showing 2 of many fetchRequest, could you give me a nudge in the right direction if I am doing it wrong?
SGK_T4T_01AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSEntityDescription *entityDiscription = [NSEntityDescription entityForName:#"Sessions" inManagedObjectContext:context];
//Swim 3 Count
NSFetchRequest *request2 = [[NSFetchRequest alloc] init];
[request2 setEntity:entityDiscription];
[request2 setResultType:NSDictionaryResultType];
NSExpression *keyPathExpression2 = [NSExpression expressionForKeyPath:#"sport"];
NSExpression *swimCountExpression = [NSExpression expressionForFunction:#"count:" arguments:[NSArray arrayWithObject:keyPathExpression2]];
NSExpressionDescription *expressionDescription2 = [[NSExpressionDescription alloc] init];
[expressionDescription2 setName:#"swimCount"];
[expressionDescription2 setExpression:swimCountExpression];
[expressionDescription2 setExpressionResultType:NSInteger16AttributeType];
[request2 setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription2]];
NSPredicate *pred2 = [NSPredicate predicateWithFormat:#"(date >= %# AND sport like %#)", swimSinceDateAsDate, sportTypeSwim];
[request2 setPredicate:pred2];
NSError *error2;
NSArray *objects2 = [context executeFetchRequest:request2 error:&error2];
if (objects2 == nil) {
NSLog(#"The fetch request returned an array == nil");
} else {
_swimTotalSwimCountLabel.text = [[NSString alloc] initWithFormat:#"%#", [[objects2 objectAtIndex:0] valueForKey:#"swimCount"]];
}
//Swim 4 Fastest 1500m Time Trial
NSFetchRequest *request3 = [[NSFetchRequest alloc] init];
[request3 setEntity:entityDiscription];
[request3 setResultType:NSDictionaryResultType];
NSExpression *keyPathExpression3 = [NSExpression expressionForKeyPath:#"time1"];
NSExpression *swimfastest1500Expression = [NSExpression expressionForFunction:#"min:" arguments:[NSArray arrayWithObject:keyPathExpression3]];
NSExpressionDescription *expressionDescription3 = [[NSExpressionDescription alloc] init];
[expressionDescription3 setName:#"swimFastest1500"];
[expressionDescription3 setExpression:swimfastest1500Expression];
[expressionDescription3 setExpressionResultType:NSInteger16AttributeType];
[request3 setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription3]];
NSString *sessType3 = #"Time Trial - 1500m";
NSPredicate *pred3 = [NSPredicate predicateWithFormat:#"(date >= %# AND sport like %# AND sessiontype like %#)", swimSinceDateAsDate, sportTypeSwim, sessType3];
[request3 setPredicate:pred3];
NSError *error3;
NSArray *objects3 = [context executeFetchRequest:request3 error:&error3];
if (objects3 == nil) {
NSLog(#"The fetch request returned an array == nil");
} else {
NSUInteger durationInSeconds = [[[objects3 objectAtIndex:0] valueForKey:#"swimFastest1500"] integerValue];
NSUInteger durationInMinutes = durationInSeconds / 60;
NSUInteger durationRemainder = durationInSeconds % 60;
_swimTt1500PaceLabel.text = [[NSString alloc] initWithFormat:#"%02i:%02i", durationInMinutes, durationRemainder];
}
Thanks in advance for any assistance, links or direction you may be able to provide...
The predicate stuff doesn't look too bad - but may I ask why you're limiting to all those NSExpressionDescriptions? Did you analyze and find that by limiting to just those properties you found concrete performance improvements? Core Data is usually pretty good at faulting/optimizing your memory, and that might clean up the statements quite a bit.

Possible to index store with Core Data when using the NSInMemoryStoreType?

I have an NSArray of a few thousand in-memory NSDictionary instances (containing strings and numbers) against which I need to perform arbitrary queries at runtime. Using filteredArrayUsingPredicate winds up yielding unacceptable performance. I could manually build up indices on each field and access those dictionaries, but I figured it might be simpler to just build up a dynamic in-memory Core Data model with indexed attributes, convert the NSDictionary instances into NSManagedObjects, and then perform the queries with NSFetchRequests.
Unfortunately, the NSInMemoryStoreType model doesn't seem to respect the "indexed" property of the NSAttributeDescription: queries against the Core Data model are taking about 50% longer than just doing the old filteredArrayUsingPredicate on the array of dictionaries. Is there some trick to getting a NSInMemoryStoreType model to create in-memory indices, or does is the attribute simply ignored? Using a SQLite store is not an option for this application, since the types of the attributes change frequently.
Here's the code I'm using to compare the performance of the two different searching mechanisms:
- (void)testInMemoryCoreDataEfficienctQuery {
static const NSInteger InstanceCount = 5000; // the number of instances to test
static NSString *EntityName = #"EntityPerformanceTest";
static NSString *AttributeName = #"attrName";
static NSString *PredicateVariable = #"predicateVariable";
NSError *error = nil;
NSManagedObjectContext *moc;
NSEntityDescription *entity;
{
NSManagedObjectModel *mom = [[NSManagedObjectModel alloc] init];
{
NSMutableArray *entities = [NSMutableArray array];
entity = [[NSEntityDescription alloc] init];
entity.name = EntityName;
NSMutableArray *attrs = [NSMutableArray array];
{
NSAttributeDescription *attr = [[NSAttributeDescription alloc] init];
attr.name = AttributeName;
attr.attributeType = NSStringAttributeType;
attr.indexed = YES; // ideally this would speed up searches on strings
[attrs addObject:attr];
}
entity.properties = attrs;
[entities addObject:entity];
mom.entities = entities;
}
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
NSPersistentStore *ps = [psc addPersistentStoreWithType:NSInMemoryStoreType configuration:nil URL:nil options:nil error:&error];
// NSPersistentStore *ps = [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:[[NSTemporaryDirectory() stringByAppendingPathComponent:[NSString randomUUID]] stringByAppendingPathExtension:#"sqlite"]] options:nil error:&error];
STAssertNotNil(ps, nil);
STAssertNil(error, #"%#", error);
moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
moc.persistentStoreCoordinator = psc;
}
[moc processPendingChanges];
[moc save:&error];
[moc reset];
STAssertNil(error, #"%#", error);
// now test searching in a MOC vs. in a collection of dictionaries
NSMutableArray *strings = [NSMutableArray array];
NSMutableArray *dicts = [NSMutableArray arrayWithCapacity:InstanceCount];
{
for (int i = 0; i < InstanceCount; i++) {
// create an arbitrary random string we will store and later query against
CFUUIDRef randomUUID = CFUUIDCreate(NULL);
NSString *uuidString = (NSString *)CFBridgingRelease(CFUUIDCreateString(NULL, randomUUID));
CFRelease(randomUUID);
[strings addObject:uuidString];
// create the dictionary
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setValue:uuidString forKey:AttributeName];
[dicts addObject:dict];
// create the managed instance
NSManagedObject *ob = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:moc];
[ob setValue:uuidString forKey:AttributeName];
}
}
[moc processPendingChanges];
STAssertEquals([strings count], [[NSSet setWithArray:strings] count], #"strings were not unique");
NSPredicate *query = [NSComparisonPredicate predicateWithLeftExpression:[NSExpression expressionForKeyPath:AttributeName] rightExpression:[NSExpression expressionForVariable:PredicateVariable] modifier:(NSDirectPredicateModifier) type:(NSEqualToPredicateOperatorType) options:(0)];
for (int iter = 0; iter < 2; iter++) {
NSFetchRequest *fetch = [NSFetchRequest fetchRequestWithEntityName:EntityName];
[fetch setFetchLimit:1];
[fetch setFetchBatchSize:1];
// time searching with Core Data
CFAbsoluteTime mocStart = CFAbsoluteTimeGetCurrent();
for (int i = 0; i < InstanceCount; i++) {
fetch.predicate = [query predicateWithSubstitutionVariables:[NSDictionary dictionaryWithObject:[strings objectAtIndex:arc4random() % strings.count] forKey:PredicateVariable]];
NSArray *results = [moc executeFetchRequest:fetch error:&error];
NSParameterAssert(!error);
NSParameterAssert(results.count == 1);
}
CFAbsoluteTime mocEnd = CFAbsoluteTimeGetCurrent();
// time searching with dictionaries
CFAbsoluteTime dictStart = CFAbsoluteTimeGetCurrent();
for (int i = 0; i < InstanceCount; i++) {
NSArray *results = [dicts filteredArrayUsingPredicate:[query predicateWithSubstitutionVariables:[NSDictionary dictionaryWithObject:[strings objectAtIndex:arc4random() % strings.count] forKey:PredicateVariable]]];
NSParameterAssert(results.count == 1);
}
CFAbsoluteTime dictEnd = CFAbsoluteTimeGetCurrent();
NSLog(#"assessed %d queries: moc=%.3f dict=%.3f", InstanceCount, mocEnd - mocStart, dictEnd - dictStart);
/*
Core Data seems to be slower, as per these results:
2012-01-10 21:19:04.247 Glimpse[9151:15503] assessed 5000 queries: moc=19.085 dict=12.186
2012-01-10 21:19:35.412 Glimpse[9151:15503] assessed 5000 queries: moc=19.001 dict=12.164
*/
}
}

Random word From Core-data (NSString)

I have a core-data model with a Entity called Goodie with Attribute called thingsYouWant of type String.
i want to pick a random word from "thingsYouWant" when u push a button, and put that in a string with format.
but i keep getting a NSString may not respond to objectAtIndex error ;-(
Update:
here is my working code:
-( void ) viewDidLoad {
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription
entityForName:#"Goodie" inManagedObjectContext:
self.managedObjectContext ]];
NSError *error = nil;
NSArray *array = [self.managedObjectContext
executeFetchRequest:request error:&error];
if (array == nil)
{
// Deal with error...
}
if(array.count > 0){
int r = random()% [array count];
goodie = [array objectAtIndex:r];
} else { // no one to fetch - generate one
goodie = [NSEntityDescription
insertNewObjectForEntityForName:#"Goodie"
inManagedObjectContext:self.managedObjectContext ];
}
- (void) winText {
NSArray *components = [[goodie thingsYouWant]
componentsSeparatedByString:#" "];
NSInteger randomIndex = (random() % [components count]);
NSString *newWord = [components objectAtIndex:randomIndex];
winLabel.text =[NSString stringWithFormat: #"Congratulations,
the carrot you have earned is -->>> %#", newWord];
}
Thank you :-D
Skov
First, array.count is an improper use of dot syntax. count is not a property of NSArray but a method call.
Second, which line is giving you the error? Are you getting it at the [array objectAtIndex:0] or at [goodie.thingsYouWant objectAtIndex:R]? If it is the latter then you need to see what the property thingsYouWant is defined as. I suspect it is a string property.
Update
If you want to grab a word out of a string then you need to split the string up into an array. Using the method -componentsSeparatedByString:. From there you can then grab one of them at random.
An example of this would be:
NSArray *components = [[goodie thingsYouWant] componentsSeparatedByString:#" "];
NSInteger randomIndex = (random() % [components count]);
NSString *newWord = [components objectAtIndex:randomIndex];
Referring to this statement of yours
Goodie with Attribute called
thingsYouWant of type String
I am with Marcus S. Zarra
Please have a look at Non-Standard Persistent Attributes to store your array in core data.