cant able to acess variable from nsarray crash at runtime - iphone

I am crashing at runtime when i pop last element from NSMuttable array.I am getting all element fine but when i acess last element it will give error.
-(id)popOperand{
id operandObject = [self.operandStack lastObject];
if(operandObject) [self.operandStack removeLastObject];
return operandObject;
}
For eg:- if in my stack i have "8"(Its NSNumber object) "+"(Its NSString object) 2(Its NSnumber Object).
NSNumber *rightOperand = [self popOperand];
NSString *operation = [self popOperand];
NSNumber *leftOperand = [self popOperand];//when i acess 8 it shows empty array other element is getting fine;
My question is why i am not able to get last object while this function is working fine for other elememts.
EDIT : At run time when after poping 2 it show stack( 8 +) but after i poped + it show stack() empty.But The "leftOperand" is not getting value. I am not using ARC.
Please ellaborate it.
Thanks.

If you aren't using ARC then you have memory management issues:
- (id)popOperand
{
id operandObject = [self.operandStack lastObject]; // Still retained by operandStack
if(operandObject) [self.operandStack removeLastObject];// Released by operandStack
return operandObject; // Could be dealloc'd any time now!
}
Try this version, which returns a retain'd and autorelease'd object, which conforms to the naming convention of the method:
- (id)popOperand
{
id obj = nil;
if ([self.operandStack count] > 0)
{
id obj = [[[self.operandStack lastObject] retain] autorelease];
[self.operandStack removeLastObject];
}
return obj;
}

Related

How do I get the index of an object in an NSArray using string value?

I want to get the index of an object within the NSMutableArray of categories.
The category object has an attribute "category_title" and I want to be able to get the index by passing the value of category_title.
I have looked through the docs and can't find a simple way to go about this.
NSArray does not guarantee that you can only store one copy of a given object, so you have to make sure that you handle that yourself (or use NSOrderedSet).
That said, there are a couple approaches here. If your category objects implement isEqual: to match category_title, then you can just use -indexOfObject:.
If you can't do that (because the category objects use a different definition of equality), use -indexOfObjectPassingTest:. It takes a block in which you can do whatever test you want to define your "test" - in this case, testing category_title string equality.
Note that these are all declared for NSArray, so you won't see them if you are only looking at the NSMutableArray header/documentation.
EDIT: Code sample. This assumes objects of class CASCategory with an NSString property categoryTitle (I can't bring myself to put underscores in an ivar name :-):
CASCategory *cat1 = [[CASCategory alloc] init];
[cat1 setCategoryTitle:#"foo"];
CASCategory *cat2 = [[CASCategory alloc] init];
[cat2 setCategoryTitle:#"bar"];
CASCategory *cat3 = [[CASCategory alloc] init];
[cat3 setCategoryTitle:#"baz"];
NSMutableArray *array = [NSMutableArray arrayWithObjects:cat1, cat2, cat3, nil];
[cat1 release];
[cat2 release];
[cat3 release];
NSUInteger barIndex = [array indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
if ([[(CASCategory *)obj categoryTitle] isEqualToString:#"bar"]) {
*stop = YES;
return YES;
}
return NO;
}];
if (barIndex != NSNotFound) {
NSLog(#"The title of category at index %lu is %#", barIndex, [[array objectAtIndex:barIndex] categoryTitle]);
}
else {
NSLog(#"Not found");
}
Not sure that I understand the question but something like this might work (assuming the Mutable Array contains objects of Class "Category"):
int indx;
bool chk;
for (Category *aCategory in theArray)
{
chk = ([[aCategory category_title] isEqualToString:#"valOfCategoryTitle"])
if ( chk )
indx = [theArray indexOfObject:aCategory];
}
Try this code much more simpler:-
int f = [yourArray indexOfObject:#"yourString"];

Spotted a leak in UITextView delegate method. Confused about solution

I've got a problem with an UITextView and one of its delegate methods in my navigation based app:
- (BOOL)textView:aView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
I managed to limit the max length of text the user can input using the above method. But I'm using a leaky array for that matter I think.
The problem is:
I want to save the amount of typed characters right in the very moment the user enters the last line of my textview. I then use that value to calculate the string length - which I compare to the textview's content size to set a limit. The code works fine - but since the method it's inside of is updating with every text input, I'm having trouble releasing the array in the right moment.
Here's some code:
if (numLines == 9)
{
if (!numCharsArray)
{
numCharsArray = [[NSMutableArray alloc] initWithCapacity:1]; // Stack trace gives this line 3,3% of the leak.
}
numChars = tView.text.length;
NSNumber *number = [[NSNumber alloc] initWithInteger:numChars]; // This line gets 77,3%.
[numCharsArray addObject:number]; // This line gets the rest, 24,3%.
[number release];
startChars = [[numCharsArray objectAtIndex:0] integerValue];
NSString *lastLine = [[NSString alloc]initWithString:[[tView text] substringFromIndex:startChars]];
CGSize lineSize = [lastLine sizeWithFont:tView.font forWidth:tView.contentSize.width lineBreakMode:UILineBreakModeWordWrap];
[lastLine release];
if (range.length > text.length)
{
return YES;
}
else if (numLines == 9 && lineSize.width >= tView.contentSize.width - 45)
{
return NO;
}
}
else
{
numCharsArray = nil;
/*
if(numCharsArray)
{
[numCharsArray release];
}
*/
}
I tried the out-commented statement above, but that gives me an app crash once I leave the last line of the textview. And as you can see in the code comments - without releasing the array I get a leak.
So how and where do I release that array correctly - keeping it safe while the user is on the last line?
Just replace with
first one
numCharsArray = [NSMutableArray array]; // you do not need to release
//explicitly as its autorelease numberWithInt
second one
NSNumber *number = [NSNumber numberWithInt:numChars]; //autorelease
NSString *lastLine = [[tView text] substringFromIndex:startChars];

EXC_BAD_ACCESS error in during fetching data from custome objects

I had stored custom objects data in Array. I am fetching data from Array of custom objects in a function. when I am calling function for first time it is working good but When I am calling it again and again I am getting EXC_BAD_ACCESS.
Here is function details.
-(void) facebookDisplayFunction:(int)atIndex {
FacebookWallData *wall = (FacebookWallData *)[facebook_wallDataArray objectAtIndex:atIndex];
NSString *friendID= wall.actor_id;
NSString *linkFetch= wall.permalink;
NSString* postID=wall.postId;
NSNumber *countNumber;
NSString *friendName=#"";
NSString* profileThumImage=#"";
for(int i=0; i< [facebook_LikesArray count];i++) {
FacebookLikes* countValues=[[FacebookLikes alloc]init];
countValues=[facebook_LikesArray objectAtIndex:i];
// NSLog(#" postId_wall %# LikePostId = %#",postID,countValues.PostID);
if([postID isEqualToString:countValues.PostID]) {
countNumber=countValues.Count;
if(countNumber>0)
friendID=countValues.Friends;
[countValues release];
break;
}
[countValues release];
}
for(int i=0;i< [facebook_FreindsArray count];i++) {
FacebookFreinds* friendsRecord=[[FacebookFreinds alloc]init];
friendsRecord=[facebook_FreindsArray objectAtIndex:i];
if([friendID isEqualToString:friendsRecord.UID]) {
friendName=friendsRecord.name;
profileThumImage=friendsRecord.pic_smal;
[friendsRecord release];
break;
}
[friendsRecord release];
}
// Adding values in table //
[imageData addObject:#"facebook.png"];
[tableList addObject:wall.messages];
[profileUserName addObject:friendName];
[linksOfFacebookData addObject:linkFetch];
[RetweetAndLikeData addObject:#"5"];
[favedProfileThumb addObject:profileThumImage];
[twitterPostID addObject:#""];
[eachPostUID addObject:friendID];
[wall release];
}
And here I am calling function.
[self facebookDisplayFunction:0];
[self facebookDisplayFunction:0]; // EXC_BAD_ACCESS error here.
Why are you allocating an object like this FacebookLikes* countValues=[[FacebookLikes alloc]init] and then assigning to this same variable the instance inside the array with this code countValues=[facebook_LikesArray objectAtIndex:i] and later on you release it with this [countValues release]? You don't know what you are doing.
Try changing this:
FacebookLikes* countValues=[[FacebookLikes alloc]init];
countValues=[facebook_LikesArray objectAtIndex:i];
to this
FacebookLikes* countValues = [facebook_LikesArray objectAtIndex:i];
and remove all occurrences of [countValues release]. Do the same for the friendsRecord in the second for-loop. Also, what is the [wall release]? Remove it!
You should not allocate any of these objects because you are actually obtaining them from that array, and not creating a new instance. That just creates a leak in your code. You should not release any of these objects because they are retained by the array, and it is responsible for releasing them whenever they are removed from the array or after the array is destroyed/deallocated. Please, rtfm
If you get the error on the line:
[self facebookDisplayFunction:0];
it seems to me that most likely the object pointed by self has been deallocated. So, the problem would not be in facebookDisplayFunction...
Could you review how you create the object pointed by self, or post the code if you need more help?

IPhone - copyWithZone leak

Testing my app on the device it returns a leak whe i call the copy of a custom object ande i can't understand why.
this is the call:
NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:5];
for (SinglePart *sp in [copyFrom partList]) {
[arr addObject:[sp copy]];
}
self.partList = arr;
[arr release];
this is the method:
- (id)copyWithZone:(NSZone *)zone {
SinglePart *copy = [[[self class] allocWithZone:zone] initWithSinglePart:self];
[copy loadImage];
return copy;
}
this is the method that is called by copyWithZone:
- (id)initWithSinglePart:(SinglePart *)copyFrom {
if (self = [super init]) {
self.imagePath = [copyFrom.imagePath copy];
self.color = [UIColor colorWithCGColor:copyFrom.color.CGColor];
self.hasOwnColor = copyFrom.hasOwnColor;
self.blendingMode = copyFrom.blendingMode;
}
return self;
}
copy returns a new object with retain count 1. Meaning you need to release the new object, which you are not doing.
NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:5];
for (SinglePart *sp in [copyFrom partList]) {
SingPart *theCopy = [sp copy];
[arr addObject:theCopy];
[theCopy release];
}
self.partList = arr;
[arr release];
Even your custom copyWithZone: method inits an object, but does not autorelease it, which is the expected behavior of a copy method. Copy must be balanced just like a retain or init, meaning you must balance it with release at some point.
Lastly, your initWithSinglePart: method leaks the imagePath as well. In this case if you declare the imagePath property as copy instead of retain then you don't need to do this manually at all. Then you simply assign the value and let the property setter do it for you.
// Header
#property (copy) NSString *imagePath;
// Now this will do the copy for you
self.imagePath = copyFrom.imagePath;
Also, is the property imagePath defined with retain or copy semantics?
If so you need to add an autorelease here:
self.imagePath = [[copyFrom.imagePath copy] autorelease];
because the default setter will retain/copy it too.
So, you either need to autorelease, or omit the "self." to bypass the default setter.
You are making a copy of sp and then adding it to the array. The array then retains the object so your retain count is now 2.
In the end you release arr, thus making the retain count of it's items 1.
You should either add another release to the sp objects, or not use copy.
Try this:
self.partList = [NSMutableArray arrayWithCapacity:5];
for (SinglePart *sp in [copyFrom partList]) {
[arr addObject:sp];
}

What is causing memory leaks?

What is causing the leaks in this code? I really cannot understand it.
On thes lines:
1: NSMutableArray * days = [[NSMutableArray alloc]init];
2: [dic setObject:days forKey:key];
3: [days addObject:value];
The whole method:
-(void) addValueToDictionary: (NSMutableDictionary *) dic withValue: (NSNumber *) value forKey: (NSString *) key {
NSMutableArray * days = [dic objectForKey:key];
if (days == nil) {
NSMutableArray * days = [[NSMutableArray alloc]init];
[days addObject:value];
[dic setObject:days forKey:key];
[days release];
days = nil;
}
else {
[days addObject:value];
}
}
BR
//Christoffer
Check to make sure that dic is released. You should NSLog retainCount before where you think the final releases are and make sure they are 1 right before the final release.
Also, run a Build and Analyze to make sure you are releasing correctly. The built in Build and Analyze doesn't find as many leaks as running scan-build with all checks, so look into installing scan-build into Xcode as well.
Using an external Xcode Clang Static Analyzer binary, with additional checks
You should be getting a warning about re-declaring days. This may be throwing the leak check off if you are using the static analyser. Modified method below. Mostly coding style changes with a little defensive coding added.
-(void) addValueToDictionary: (NSMutableDictionary *) dic withValue: (NSNumber *) value forKey: (NSString *) key
{
if (nil == dic || nil == key || nil == value) return; // bail out on nil parameters
if (![dic objectForKey:key]) {
NSMutableArray * days = [[NSMutableArray alloc] init];
[dic setObject:days forKey:key];
[days release];
}
[[dic objectForKey:key] addObject:value];
}
Have you tried to change the name of the variable NSMutableArray *days within the if? Don't you get a warning because of that?
There's nothing wrong with that particular piece of code (other than the slightly questionable redefinition of days in the inner scope). Somewhere else you are retaining but forgetting to release the object you put in the dictionary.
change NSMutableArray initialization to...
NSMutableArray * days = [NSMutableArray array];