Number of Objects (3) not equal to number of keys(8) - iphone

Ok, so the issue is coming from trying to pull data from a sqlite DB and place it in an array for a scroll view display. Im using FM Database library to connect to sql database
The code is as follows:
NSMutableArray *data = [[NSMutableArray alloc] init];
FMResultSet *result = [[[StorageTank sharedStorageTank] DB]
executeQuery:#"SELECT * FROM table"];
while([result next])
{
NSArray *values = [[NSArray alloc] initWithObjects:
[[NSNumber alloc] initWithInt:[result intForColumn:#"id"]],
[[NSNumber alloc] initWithInt:[result intForColumn:#"count"]],
[[NSNumber alloc] initWithInt:[result intForColumn:#"required"]],
[result stringForColumn:#"image_portrait"],
[result stringForColumn:#"image_landscape"],
[[NSNumber alloc] initWithInt:[result intForColumn:#"end_date"]],
[[NSNumber alloc] initWithInt:[result intForColumn:#"active"]],
[result stringForColumn:#"merchant"], nil];
NSLog(#"%#", values);
NSArray *keys = [[NSArray alloc] initWithObjects: #"id",#"count",#"required",
#"image_portrait",#"image_landscape",
#"end_date",#"active",#"merchant",nil];
NSLog(#"%#", keys);
NSDictionary *row = [[NSDictionary alloc] initWithObjects: values forKeys: keys];
[data addObject: row];
}
NSArray *resultArray = [[NSArray alloc] init];
resultArray = data;
So, obviously from the code i've tested to make sure the values count is equal to the keys count... yet Im still getting this error:
"Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSPlaceholderDictionary initWithObjects:forKeys:]: number of objects (3) not equal to number of keys (8)'"
I can't understand for the life of me why the count would differ if when I print out the values array I see 8 values... which should match my 8 keys? and they are correct?
Any help/direction would be greatly appreciated!
Thanks,

Is the fourth item in your values array:
[result stringForColumn:#"image_portrait"]
returning nil? That's the value that tells -initWithObjects that the list is done.

Related

Using a nested NSMutableDictionary

simple question, I need to structure data in the following format:
UserID:
1 {
Name = Bob
Surname = Hope
}
2 {
...
I can used an NSMutableDictionary to add a single layer with keys, but I am unable to create a child associate with a certain key.
I have tried creating a mutable dictionary and assigning that to a key:
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
NSArray *keys = [[NSArray alloc] initWithObjects:#"Name", #"Surname", nil];
NSArray *details = [[NSArray alloc] initWithObjects:#"Bob",#"Hope", nil];
NSDictionary *person = [[NSMutableDictionary alloc] initWithObjects:details forKeys:keys];
[dic setValue:#"1" forKey:#"id"];
[[dic objectForKey:#"id"] setDictionary: person];
I think it is better to use an array of dictionaries, each dictionary representing a user.
NSMutableArray *users= [[NSMutableArray alloc] init];
NSArray *keys = [[NSArray alloc] initWithObjects:#"Name", #"Surname", nil];
NSArray *details = [[NSArray alloc] initWithObjects:#"Bob",#"Hope", nil];
NSDictionary *person = [[NSMutableDictionary alloc] initWithObjects:details forKeys:keys];
[users addObject:person];
u can also set the objects for dictionary in this way
[dic setObject:person forKey:#"id"];

-[__NSCFString objectForKey:]: unrecognized selector sent to instance

// Configure the cell.
cell.textLabel.text = [[self.drinks objectAtIndex:indexPath.row] objectForKey:#"Name"];
return cell;
The above code is generating this exception. What could be causing this and how can I fix it?
My Understand from Your question
You have array of drinks like
Drink *d1 = [[Drink alloc] init]
d1.name = #"Drink1";
d1.price = [NSNumber numberWithFloat:25.0];
Drink *d2 = [[Drink alloc] init]
d2.name = #"Drink2";
d2.price = [NSNumber numberWithFloat:35.0];
OR
NSArray *values1 = [NSArray arrayWithObjects:#"Drink1",[NSNumber numberWithFloat:25.0], nil];
NSArray *keys1 = [NSArray arrayWithObjects:#"Name",#"price", nil];
NSDictionary *d1 = [[NSDictionary alloc] initWithObjects:values1 forKeys:keys1];
NSArray *values2 = [NSArray arrayWithObjects:#"Drink2",[NSNumber numberWithFloat:55.0], nil];
NSArray *keys2 = [NSArray arrayWithObjects:#"Name",#"price", nil];
NSDictionary *d2 = [[NSDictionary alloc] initWithObjects:values1 forKeys:keys1];
self.drinks = [NSArray arrayWithObjects:d1,d2, nil];
[d1 release];
[d2 release];
From the above case
cell.textLabel.text = [[self.drinks objectAtIndex:indexPath.row] objectForKey:#"Name"];
the above statement is correct
You are getting exception means, You are inserting the objects into drinks array, that supports Key Value Pairs data and that is String Data.
I hope you are having like this
self.drinks = [NSArray arrayWithObjects:#"Drink1",#"Drink2", nil];
In this above case you have to go with
cell.textLabel.text = [self.drinks objectAtIndex:indexPath.row];
first try to determine what object is self.drinks,
then you can go finer depending if is an array with dictionaries?
do a log
[self.drinks objectAtIndex:0]
what do you see?

I cant set an array with a series of images stored in a my core data store ios

This has been bugging me for 2 days now and I cant get my head around it. I want to extract several images that are stored in my core data store. The images are user selected using the image picker and rendered to a size of less then 70KB, transformed to data and popped into the core data store. The images are to be used in a slideshow. Entity is called ImageCD and the image is stored in the attribute friendsPhoto. I also allocate a date attribute to sort the images. This is done when the image is saved and is also an attribute of ImageCD.
I am using the following code to TRY and set the array but it does not return anything. im not getting a (NULL) readout on the debugger just that "Number of elements in array = 0;"
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"date" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:&sortDescriptor count:1];
NSLog(#"array's content sortDe:%#",sortDescriptors);
NSMutableArray* sortedImages = [[NSMutableArray alloc] initWithObjects:imageCD.friendsPhoto, nil];
[sortedImages sortUsingDescriptors:sortDescriptors];
[sortDescriptor release];
[sortDescriptors release];
NSLog(#"array's content:%#",sortedImages);
imageArray = [[NSMutableArray alloc]init] ;
self.imageArray = sortedImages;
NSLog (#"Number of elements in array = %i", [imageArray count]);
self.theImageView.animationImages = [[NSArray alloc] initWithArray:imageArray];
NSLog(#"animationImages:%#",self.theImageView.animationImages);
So, what am I doing wrong? I have my suspicions it is something to do with this line of code...
NSMutableArray* sortedImages = [[NSMutableArray alloc] initWithObjects:imageCD.friendsPhoto, nil];
But cant work out what the alternate should be. I will be forever indebted to whoever can correct my mistake. I thank you in advance and please, let me know if you require any further information, a beer or a bacon sandwich.
Ohh, to save my sanity, I sanity checked the images by adding a class from my previous app (My Outfit) which utilizes this approach to retrieving images from core data BUT within a tableView, so called in cellForRowInIndexPath etc. and all the images are sound.
DetartrateD
2011-08-04 19:40:33.051 My Class Book[1027:707] After managedObjectContext: <NSManagedObjectContext: 0x1821b0>
2011-08-04 19:40:33.057 My Class Book[1027:707] array's content sortDe:(
"(date, ascending, compare:)"
)
2011-08-04 19:40:33.059 My Class Book[1027:707] array's content:(
)
2011-08-04 19:40:33.061 My Class Book[1027:707] Number of elements in array = 0
2011-08-04 19:40:33.063 My Class Book[1027:707] animationImages:(
)
Now fixed with these changes
...
NSMutableArray *mutableFetchResultsA = [[managedObjectContext executeFetchRequest:requestA error:&error] mutableCopy];
if (mutableFetchResultsA == nil) {
NSLog(#"Testing: No results found");
}
else {
NSLog(#"Testing: %d Results found.", [mutableFetchResultsA count]);
NSLog(#"array's content sortDe:%#",mutableFetchResultsA);
}
[sortDescriptor release];
[sortDescriptors release];
imageArray = [[NSMutableArray alloc]init] ;
self.imageArray = [mutableFetchResultsA valueForKey:#"friendsPhoto"];
[mutableFetchResultsA release];
[requestA release];
...
Assuming that the images are stored as NSData * attributes in the ImageCD entity, here is what you need to do:
self.imageArray = [self getImagesInManagedObjectContext:self.managedObjectContext];
Here is the getImagesInManagedObjectContext: method. This method retrieves from the Core Data store the ImageCD objects, sorted using your attribute as required, then creates and returns an autoreleased NSMutableArray of UIImage * objects or nil if no objects have been found.
- (NSMutableArray *) getImagesInManagedObjectContext:(NSManagedObjectContext *)moc{
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"ImageCD" inManagedObjectContext:moc];
[request setEntity:entity];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"date" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
NSError *error = nil;
NSMutableArray *array = [NSMutableArray arrayWithArray: [moc executeFetchRequest:request error:&error]];
[request release];
[sortDescriptor release];
[sortDescriptors release];
if (array && [array count] && !error){
// create an array of images
NSMutableArray *images = [[NSMutableArray alloc] init];
for(ImageCD *obj in array){
UIImage *img = [UIImage imageWithData: (NSData *) obj.friendsPhoto];
[images addObject:img];
}
return [images autorelease];
}
else
return nil;
}

NSMutableDictionary confused over how to use keys with certain code?

I'm getting data from a database and I need to add the string field value and the record id.
However, I need this to work with some existing code...
I'm replacing this (see code below) and getting data from my database.
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
self.allCategories = dict;
[dict release];
This is the file it loads...
But needs to work with these key and value search functions.
- (void)resetSearch {
NSMutableDictionary *allCategoriesCopy = [self.allCategories mutableDeepCopy];
self.Categories = allCategoriesCopy;
[allCategoriesCopy release];
NSMutableArray *keyArray = [[NSMutableArray alloc] init];
[keyArray addObject:UITableViewIndexSearch];
[keyArray addObjectsFromArray:[[self.allCategories allKeys]
sortedArrayUsingSelector:#selector(compare:)]];
self.keys = keyArray;
[keyArray release];
}
.
- (void)handleSearchForTerm:(NSString *)searchTerm {
NSMutableArray *sectionsToRemove = [[NSMutableArray alloc] init];
[self resetSearch];
for (NSString *key in self.keys) {
NSMutableArray *array = [Categories valueForKey:key];
NSMutableArray *toRemove = [[NSMutableArray alloc] init];
for (NSString *name in array) {
if ([name rangeOfString:searchTerm
options:NSCaseInsensitiveSearch].location
== NSNotFound)
[toRemove addObject:name];
}
if ([array count] == [toRemove count])
[sectionsToRemove addObject:key];
[array removeObjectsInArray:toRemove];
[toRemove release];
}
[self.keys removeObjectsInArray:sectionsToRemove];
[sectionsToRemove release];
[table reloadData];
}
Keep getting an error from this code...
NSDictionary *arrayTmp= [[NSDictionary alloc] init];
... loop records
int cid = sqlite3_column_int(statementTMP, 0);
NSString *category = [[NSString alloc]
initWithUTF8String:(char *)sqlite3_column_text(statementTMP, 1)];
[arrayTmp setObject:category forKey:[NSString stringWithFormat:#"%i", cid]];
Error caused by line above
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFString count]: unrecognized selector sent to instance 0x4d4c500' * Call stack at first throw *
... end loop
self.allCategories = arrayTmp;
[arrayTmp release];
The error message says you are sending 'count' to an instance of NSString.
My guess is that the plist at 'path' (the plist file) has a string as one of the values. As you iterate through 'Categories' you expect each value to be an array (i.e. 'NSMutableArray *array = [Categories valueForKey:key];') and send that value a 'count' message.
One of the objects you expect to be an array is a string.
setValue is key-value coding method. You should use setObject:forKey: instead.
arrayTmp should be inited with [[NSMutableDictionary alloc] init].
First of all, you're using wrong method:
[arrayTmp setValue:category forKey:[NSString stringWithFormat:#"%i", cid]];
which method used for key-value coding (you can find more about KVO here).
The method you're looking for is:
[arrayTmp setObject:category forKey:[NSString stringWithFormat:#"%i", cid]];
Moreover, you should NSMutableDictionary. The NSDictionary you're using does not support mutation. (you can find more info on NSMutableDictionary here).
Cheers,
Pawel

crashed on iphone but not on simulator

It is really mind boggling to find out many differences between the iphone and the simulators. I spent several hours trying to figure out why my application ran on the simulator but crashed on my iphone device. It turns out the culprit is sortedArrayUsingDescriptors. Are there more get-you like this? Please share with me.
To share with you on the issue and the fixes:
Code crashed on iphone but not simulator
NSSortDescriptor* aDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"count" ascending:NO] autorelease];
NSArray* anNsArray = [[NSArray alloc] init];
NSArray* aSortedNsArray = [[NSArray alloc] init];
aSortedNsArray = [anNsArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:aDescriptor]];
The issue is on [NSArray arrayWithObject:aDescriptor];
The fixes are to create an Array to store it:
NSArray* descriptorArray = [[NSArray alloc] initWithObjects:countDescrp, nil];
aSortedNsArray = [anNsArray sortedArrayUsingDescriptors:descriptorArray];
NSSortDescriptor* aDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"count" ascending:NO] autorelease];
NSArray* anNsArray = [[NSArray alloc] init];
NSArray* aSortedNsArray = [[NSArray alloc] init];
aSortedNsArray = [anNsArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:aDescriptor]];
This is a wrong initialization mechanism, and if the code snippet is complete, your problem lies on the anNsArray object that's empty.
You also do not need to initialize the aSortedNsArray.
So it should be:
NSSortDescriptor* sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"count" ascending:NO] autorelease];
// Assume you return it as array of objects from a property or method
NSArray *array = [self objects];
NSArray *sortedArray = nil;
if ([array count] > 0) {
sortedArray = [array sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
}
// Then you check the sortedArray
if (sortedArray == nil || [sortedArray count] == 0)
[self somethingIsWrong];
arrayWithObject: (autoreleased) or initWithObject: (manual) is just a different way to allocate NSArray object. It won't cause crashes normally. Because what you care about is the sortedArray not retaining the descriptors array object.