Objective-C crash issue: NSInvalidArgumentException - iphone

I am stuck in it for a long time, but can not find a solution. Here is my code:`
NSLog(#"[tempArray retainCount]: %d",[tempArray retainCount]);
tempArray = [[NSMutableArray alloc] initWithArray:[allRemainingProductsDictionary objectForKey:[[allRemainingProductsDictionary allKeys]objectAtIndex:counter]]];
NSMutableDictionary *tempDictionary = [[NSMutableDictionary alloc] init];
[tempDictionary setObject:productName forKey:#"name"];
[tempArray release];
I am getting a NSException crash with this report. Please help.

The method getObjects:range: that is being sent to your NSDictionary instance is a NSArray method.
You're probably trying to to your initWithArray passing a NSDictionary instead of a NSArray.

Is the NSLog entry showing up? If not, it's because tempArray does not respond to retainCount. You don't need to worry about anything with release or retain if you're using Xcode 4.2 with ARC for iOS 5 (which you should, unless you have legacy code).
Otherwise, somewhere you're sending an object a message it doesn't respond to.

Related

NSMutableArray removeAllObjects causing crash

I have a couple of arrays that I am trying to clear all objects from, but using removeAllObjects crashes the app and returns sigabrt. During my research I've found that although I am creating NSMutableArrays I could be creating an instance of a NSArray, but I am not sure if I am doing this or not... Here is everything I do to the arrays
ballArray = [[NSMutableArray alloc] init];
ballVelocityArray = [[NSMutableArray alloc] init];
[ballArray addObject:MyUIImageView];
[ballVelocityArray addObject:[NSValue valueWithCGPoint:myCGPoint]];
[ballVelocityArray replaceObjectAtIndex:SomeIndex withObject:[NSValue valueWithCGPoint:NewVelocity]];
[ballArray removeAllObjects];
[ballVelocityArray removeAllObjects];
That is everything I have done and I can't figure out why it keeps crashing... if there is only one object in the arrays it works fine, otherwise it crashes
Any help would be greatly appreciated!!
It's most likely because you are not managing memory correctly on one of the objects the array contains. When you remove an object from an array its retain count is decremented once.
You can put a break point on the line where you clear the array and use the debugger to see which object in there is invalid.
ballArray = [[NSMutableArray alloc] init];
ballVelocityArray = [[NSMutableArray alloc] init];
After allocating object you are also releasing the object in dealloc function or somewhere else check this.If you are doing so then I would like to inform you that
[ballArray removeAllObjects];
[ballVelocityArray removeAllObjects];
removeAllObjects is not only removing all objects of array but also release the array object from memory so if again you are releasing the array object the memory pointer will reach on -1 and the application will crash.
So, make sure that You have not to release array object it you are already using
[ballArray removeAllObjects];
[ballVelocityArray removeAllObjects];
functions.

About memory management in iPhone

Please clarify the following thing.
Everyone knows that; if we are using alloc, retain, new and etc..., we have to release it. For remaining things, we have to use autorelease. My doubt is;
-(NSArray*)getArray{
NSArray *array = [[NSArray alloc] initWithObjects:#"1", #"2", #"3", #"4", #"5", nil];
return [array autorelease];
}
NSArray *arr = [self getArray];
---
---
What we have to do the arr?
EDIT:
NSString *str = [NSString stringWithFormat:#"Welcome..."];
If we are using the above statement, we should call autorelease. But I want to know, what is happening in the stringWithFormat:method. How it is returning NSString.
Thanks.
If you are planning to return the array, go ahead and use the [NSArray arrayWithObjects:#"1", #"2", etc, nil] instead.
You then just need to remember to retain it if you want to hold on to it for longer then the autorelease pool will hold it.
The autorelease pool will give it a retain count of 1, and then automatically decrement it by 1 when the release pool gets called. Without retaining it in the calling function, this object will eventually disappear.
You don't have to do anything with arr since you didn't explicitly alloc, copy, new, or retain it in its current scope. It's already been added to the autorelease pool so it'll automatically be cleaned up once you're done with it.
EDIT: In your edited question, [NSString stringWithFormat:] returns an autoreleased string. It's basically doing the same thing as you're doing in your getArray method. It builds a NSString (or related) object and autoreleases it before it's returned.
You should retain:
[[self getArray] retain];
Or return non-autoreleased object in getArray.
Your getArray method is returning an NSArray that _will_be_ released when the stack fully unwinds.
In the method where you are calling your getArray method, it is safe to use the NSArray, but if you want to keep it, and use it after your current method returns, you will need to retain the NSArray with [arr retain].
Answer to your new question
Class methods, like [NSString stringWithFormat:] or like [NSURL URLWithString:] return objects that have been autoreleased. This is a convention, a standard practice in UIKit and the Apple frameworks.

Objective C two-dimensional array memory issues

I'm trying to declare a two-dimensional array as an instance variable in Objective C. I've got the NSMutableArray in the header (data), along with the #property (nonatomic, retain). In viewDidLoad: I have:
data = [[NSMutableArray alloc] init];
[data addObject:[[NSArray alloc] initWithObjects:#"Cheese", #"Meat", #"Veggie", nil]];
[data addObject:[[NSArray alloc] initWithObjects:#"Sandwich", #"Soup", #"Stew", nil]];
I can NSLog the array within the method and it is correct, however when I try to Log it from a separate method I get nothing (just "#"), and if I try to access with
NSInteger num = [[data objectAtIndex:component] count];
it crashes with no error in the log. I'm sure this is something to do with not allocating memory properly, however I am new to Obj C and haven't worked with a C-style language in many years. FWIW, I have tried many variants of this that all fail, including using NSArray instead of mutable, [NSArray arrayWithObjects] instead of [[NSArray alloc] initWithObjects], and every combination in between.
try creating the outer array like this:
self.data = [NSMutableArray arrayWithCapacity:2]; // assuming you're only adding 2 inner arrays.
The following may be a right way.
self.data = [NSMutableArray array];
[data addObject:[NSArray arrayWithObjects:#"Cheese", #"Meat", #"Veggie", nil];
[data addObject:[NSArray arrayWithObjects:#"Sandwich", #"Soup", #"Stew", nil];
Note that, as #jamihash commented above, you need self.data to properly retain the array. And, there is no need to alloc the NSArray which you are adding to data.
As a side issue, you're retaining the child arrays twice. They get retained when you add them to your NSMutableArray, so you should probably autorelease them on creation or create them with one of the NSArray methods that returns an autoreleased array.
Your code by itself shouldn't crash. You should look into where and when you release and retain the NSMutableArray. You could post more of the code and I'm sure somebody will spot the problem.

addObject to NSMutableArray not working for iPhone App

There have been a few threads on this topic but none have been able to solve my problem. Essentially I am trying to add a custom object to an NSMutableArray and it doesn't seem to be adding. I don't get any errors but I get a warning saying that my array is an "unused variable" so it looks like it is not getting used. See code below. Any help is appreciated!
Here is the initialization in the app delegate (on run time it says this array is not being used):
NSMutableArray *organArray = [[NSMutableArray alloc] init];
Here is my object class organ.m (I am importing the app delegate, the rootviewcontroller and the organ.h file)
Organ *organObj = [[Organ alloc] initWithPrimaryKey:primaryKey];
organObj.organName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt,1)];
organObj.isDirty = NO;
[appDelegate.organArray addObject: organObj];
[organObj release];
I know the organObj.organName is getting the correct values from my sqlite db because I can output them to the console. They just don't seem to be getting added to the array and the fact that it says the array is not being used means something is wrong.
Thanks in advance
Just a guess but if organArray is intended to be a member of your app delegate, you are creating a new organArray when prefixing it with "NSMutableArray" so if I understand your code, change your app delegate to:
organArray = [[NSMutableArray alloc] init];
instead of:
NSMutableArray *organArray = [[NSMutableArray alloc] init];

Why Instruments report a leak?

I am developing an iphone app. Instruments reported a leaked object ServiceTypes. Below is the relevant code. Does anyone have any ideas? Thanks a lot for your help.
ServiceTypes *serviceTypes = [[ServiceTypes alloc] init];
if ([userConnection getServiceTypes:serviceTypes]) {
if ([serviceTypes.types length] > 0) {
NSArray *array = [[NSArray alloc] initWithArray:[serviceTypes.types componentsSeparatedByString: SERVICE_TYPE_DELIMITOR]];
serviceRequestTypes = [[NSMutableArray alloc] initWithArray:array];
[array release];
}
}
[[self typesTableView] reloadData];
[serviceTypes release];
It doesn't look like serviceTypes is being leaked. From the code you posted, serviceTypes is always released at the end of the method, and it doesn't appear to be retained anywhere in your sample. My question is: what happens inside getServiceTypes:. Does that method retain the serviceTypes parameter?
One more thing. If serviceRequestTypes is an instance variable (and it looks like it is), then you may be leaking memory by reassigning it without releasing the existing serviceRequestTypes object first. You should either rewrite serviceRequestTypes to be a property and use a synthesized accessor or make sure to release it every time before assigning. If its current value is nil, no big deal; the release message will simply be ignored. For example:
[serviceRequestTypes release];
serviceRequestTypes = [[NSMutableArray alloc] initWithArray:[serviceTypes.types componentsSeparatedByString:SERVICE_TYPE_DELIMITER]];