crashed on iphone but not on simulator - iphone

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.

Related

-[__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?

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

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.

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;
}

iPhone memory leak and release problem on sorted array

I'm having some troubles with the code below:
NSSortDescriptor *idDescriptor = [[[NSSortDescriptor alloc] initWithKey:key ascending:ascending] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:idDescriptor];
NSArray *orderArray = [array sortedArrayUsingDescriptors:sortDescriptors];
NSMutableArray *result = [NSMutableArray arrayWithArray:orderArray];
If I use this code, Instruments says I have a memory leak, why?
Using this code:
NSSortDescriptor *idDescriptor = [[[NSSortDescriptor alloc] initWithKey:key ascending:ascending] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:idDescriptor];
NSArray *orderArray = [array sortedArrayUsingDescriptors:sortDescriptors];
NSMutableArray *result = [[NSMutableArray alloc] initWithArray:orderArray];
I receive the leak warning too, however, if I autorelease the object result, a memory error happens.
Here is a better answer I think.
- (NSMutableArray *) orderArray:(NSMutableArray *)array ByKey:(NSString *)key ascending:(BOOL)ascending
{
NSSortDescriptor *idDescriptor = [[[NSSortDescriptor alloc] initWithKey:key ascending:ascending]];
NSArray *sortDescriptors = [NSArray arrayWithObject:idDescriptor];
NSArray *orderArray = [array sortedArrayUsingDescriptors:sortDescriptors];
NSMutableArray *result = [[[NSMutableArray alloc] initWithArray:orderArray]];
[release idDescriptor];
return [result autorelease];
}
So, you allocate idDescriptor, then you use it, finally release it. Since you're returning result, you can autorelease it with the return. I have one more question though. Do you reference result elsewhere in your code?

Initializing a class. Can you see any problems with this?

-(id)init {
if (self = [super init]) {
self.name = [[NSString alloc] init];
self.type = [[NSString alloc] init];
self.phoneNumber = [[NSString alloc]init];
self.webAddress = [[NSString alloc] init];
NSMutableArray *pricesArray = [[NSMutableArray alloc] init];
NSMutableArray *poolsArray = [[NSMutableArray alloc] init];
self.prices = pricesArray;
self.pools = poolsArray;
[pricesArray release];
[poolsArray release];
//Create the address dictionaries
NSMutableDictionary *addressItems = [[NSMutableDictionary alloc] initWithObjectsAndKeys:#"", KAddressStreet1Key, #"", KAddressStreet2Key, #"", KAddressBoroughKey, #"", KAddressCityKey, #"", KAddressCountyKey, #"", KAddressPostCodeKey, #"" ,KAddressCountryKey, nil];
//Add dictionary to the array to contain address values
self.address = addressItems;
[addressItems release];
}
return self;
}
I'm currently doing a massive round of debugging thanks to EXC_BAD_ACCESS errors.. grr.
Does the code above seem fine and logical for a class init method? Basically I'm getting the EXC_BAD_ACCESS errors when I release both the pools (mutable array and the dictionary).
How are your properties declared? If they are not declared with retain then most of your objects will be deallocated at the end of this method.
You're leaking objects with each allocation for the string properties. Other than that, I don't notice anything wrong. How are the AddressXKeys defined?