Hi :) This is messing me up quite the bit...
Say I have this method:
-(void) initEvent:(NSMutableArray*) Day day:(float)DayNum
{
//[Day addObject:[[[LifeEvent alloc] init] initVars:100]];
[Day addObject:#"Hello"];
[Day addObject:#"there :)"];
}
I call that method in a small loop:
for (int i = 0; i < 7; i++)
{
NSMutableArray * DayTMP = [[NSMutableArray alloc] init];
[self initEvent:DayTMP day:i];
}
Theoretically, this should pass DayTMP to the function, and add data to that variable. Not the case, instead, it creates a copy of DayTMP, adds data to that value, and drops it. DayTMP never gets modified!
I need to know how to pass values to functions as pointers, not copies, so that DayTMP is modified.
Actually what you are doing here is that you are creating 7 NSMutableArray type objects and the same variable name DayTMP is used for all of them ....... so loose the access of all 6 of them and and you only can access the last one because in every itteration of the loop DayTMP is pointing to new location ....... so to achieve what you want you should do following...
NSMutableArray * DayTMP = [[NSMutableArray alloc] init];
for (int i = 0; i < 7; i++)
{
[self initEvent:DayTMP day:i];
}
Normally your code should work fine except that you never release DayTMP creating a memory leak. You are indeed passing a pointer to an NSMutableArray : (NSMutableArray*).
You "init" DayTMP inside the loop!!!
that means you create (and never release!) the same object many time, overriding it every time, so you kill the old one each time, and you get just the last one: it's a memory error
Related
I am developing an iphone application which has some data stored in a sqllite database. When my view loads i would like to load the data from the database on a background thread. The problem is the application keeps crashing and i dont know why.
The code:
-(id) init
{
if((self=[super init]))
{
[self performSelectorInBackground:#selector(loadList) withObject:nil];
}
}
-(void) loadList
{
#autoreleasepool
{
Loader * loader = [[Loader alloc] init];
NSMutableArray * array = [loader getItemList];
[array retain];
NSLog(#"Got %d items",[array count]);
[self performSelectorOnMainThread:#selector(createList:) withObject:array waitUntilDone:false];
[loader release];
}
}
-(void) createList: (NSMutableArray*) array
{
items = array;
int i;
Item * it;
for(i = 0; i < [items count]; i++)
{
it = [items objectAtIndex: i];
[it getName]; // crashes
// populate the list
}
}
Loader returns a NSMutableArray with Item objects. The application crashes when i call the item getName (which returns a NSString*). From what i understand it crashes because the item name properties is being released. What am i doing wrong?
Thanks!
It's likely to be a problem with whatever type of object you're using to populate array.
I'm unable to find finger-on-paper proof but I'm confident that performSelectorOnMainThread:withObject:waitUntilDone: retains its object. However if each of the items in array keeps a reference to loader then they need to take responsibility for retaining that object. It looks like you're attempting to keep it alive manually but — as Chuck alludes to — your call to performSelector... will return instantly and not wait for the call you've made to complete.
This particular bug appears to be that you're passing waitUntilDone:NO, so the array is being released immediately and consequently so are its items.
But in general, UIKit is not thread-safe, so this is just a touchy design. I would probably put the loading of this stuff in another class that handles the task for you instead of right in the view.
I'd put a breakpoint on the line:
it = [items objectAtIndex: i];
Then type
po it
in the debugger, and see what's in the name field. As a guess, I'd say one of two things: 1) the field that getName returns isn't initialized with an object (i.e. isn't a real NSString *) or that you're getting a C string from SQLite (which is what it usually returns) and you're trying to treat it as an NSString *. If it's the latter you can use [myCString stringWithUTF8String] to convert the C string into an NSString *
I'm getting a memory leak when I`m trying to reset a table view, I thought I could just put release before, but this doesn't help.
What do I need to do here ?
-(void) resetTable{
recordOffset = 10;
rOFactor = 0;
booShowMoreCell = false;
self.transactionsArray = [[NSMutableArray alloc] init]; // leak here
}
Assuming that transactionsArray is a retained property, the problem you are having is that the NSMutableArray is being retained twice.
When you set a retained property it releases the old value, and retains the new (incoming) value. The alloc method also retains the object.
So
// \/--- retain count = 2 \/-- retain count = 1
self.transactionsArray = [[NSMutableArray alloc] init];
The shortest way to resolve this is autorelease the NSMutableArray:
self.transactionsArray = [[[NSMutableArray alloc] init] autorelease];
There's a convenience method way for the above line:
self.transactionsArray = [NSMutableArray array];
As I can't see a [tableView release]-call in this code, that's what's missing - you aren't releasing the tableView before allocating a new one on top of it. That means you're adding a retain count, without removing one first. Adding the release will fix the leak.
On the first sight I would say that you just overwrite the pointer with a reference to a new object and forgetting the old reference which points to an object that was not released yet. As long as you do not use ARC you should use
[self.transactionsArray release]; // Be sure it was alloced before
self.transactionsArray = [[NSMutableArray alloc] init];
Tons of similar questions, but none of their answers seem to answer mine...
I'm creating my array as such:
imgArray = [NSMutableArray arrayWithCapacity:10];
Later (in another function) I am trying to add an object to it:
Attachment newAttachment = [[[Attachment alloc] init] autorelease];
newAttachment.fileName = filename;
newAttachment.file = file;
[imgArray addObject:newAttachment];
This results in the iPhone app freezing up. The simulator seems fine; the clock on the status bar keeps ticking, I don't get any error messages, but my app is no longer responding.
What am I doing wrong?
It seems you are not retaining imgArray. Are you? Try,
imgArray = [[NSMutableArray alloc] initWithCapacity:10]
if not.
just do
imgArray = [[NSMutableArray arrayWithCapacity:10] retain];
all class methods if return an object is returned with retain count 1 and object already in autorelease pool so if want to use that object beyond the current working block the you should always retain that object because then reference is lost outside the block.
i have a problem.
When i compile my program there isn't a error but, when i start it these retern with “EXC_BAD_ACCESS”.
I looking for the error with the debug and i find it in these method but i don't understand where...
PS:the program enters in the loop sometimes.
-(void)updateMinPosition{
float valueMinX = 150;
float valueMinY = 150;
float valueMinZ = 150;
NSString *nameMinimoX = [NSString stringWithFormat:#"default"];
NSString *nameMinimoY = [NSString stringWithFormat:#"default"];
NSString *nameMinimoZ = [NSString stringWithFormat:#"default"];
for(int i = 0; i< [arrayPosizioniMovimento count]; i++){
//Posizione is my class. It contain a NSString name, 3 float valueX, valueY, valueZ
Posizione *tempPosition;
tempPosition = [[Posizione alloc]init];
tempPosition = [arrayPosizioniMovimento objectAtIndex:i];
if(tempPosition.valueX <= valueMinX){
valueMinX = tempPosition.valueX;
nameMinimoX = tempPosition.nome;
}
if(tempPosition.valueY <= valueMinY){
valueMinY = tempPosition.valueY;
nameMinimoY = tempPosition.nome;
}
if(tempPosition.valueZ <= valueMinZ){
valueMinZ = tempPosition.valueZ;
nameMinimoZ = tempPosition.nome;
}
[tempPosition dealloc];
}
labelMinX.text = nameMinimoX;
labelMinY.text = nameMinimoY;
labelMinZ.text = nameMinimoZ;
}
For the 1st glance there're several problems with your code:
Posizione *tempPosition;
tempPosition = [[Posizione alloc]init];
tempPosition = [arrayPosizioniMovimento objectAtIndex:i];
Here in the second line you create new Posizione instance and right after that assign another value to the same variable. In effect that will mean that your created instance will be never used and cause memory leak. To use element from array just write
Posizione *tempPosition = [arrayPosizioniMovimento objectAtIndex:i];
The second one - is the following line
[tempPosition dealloc];
First of all you should never call this method directly but rather send an object -release message - it will be deallocated automatically when its retain count becomes 0. In your case you do not retain tempPosition object in that code so there;s no need to release it here - just remove that line.
P.S. Using fast enumeration can also make your code more readable and less error prone:
for (Posizione *tempPosition in arrayPosizioniMovimento){
if(tempPosition.valueX <= valueMinX){
...
It looks like it may be the [tempPosition dealloc] call. You're declaring that variable and doing an alloc/init on it but then just assigning it to the object within the array, so the alloc/init is unneeded. When you make the call to dealloc at the bottom you're releasing that object that resides in the array, so your array will now have a null value which will cause the EXEC.... error
You can enable Objective-C Exception breakpoints to pinpoint the line.
On thing that jumps out is
[tempPosition dealloc];
I'm not sure what to tell you to do. You need to call release not dealloc.
[tempPosition release];
But im not sure how that fits into the rest of your code, where you are allocating a variable then immediately assigning it another value.
I think you should just remove the alloc and dealloc
so delete:
//Posizione is my class. It contain a NSString name, 3 float valueX, valueY, valueZ
Posizione *tempPosition;
tempPosition = [[Posizione alloc]init];
and
[tempPosition dealloc];
Pease show how do you initialize arrayPosizioniMovimento.
If you initialized it like arrayPosizioniMovimento = [NSMutableArray arrayWithCapacity:n]; than you'll need to add [arrayPosizioniMovimento retain];
I have a table view in which I'm using sectionIndexTitlesForTableView to display an index. However, when I scroll the table, the index scrolls with it. This also results in very slow refreshing of the table. Is there something obvious I could be doing wrong? I want the index to remain in place on the right while the table scrolls. This is the code I'm using for the index titles:
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
[tempArray addObject:#"A"];
[tempArray addObject:#"B"];
[tempArray addObject:#"C"];
[tempArray addObject:#"D"];
...
return tempArray;
}
You really should be creating the index list somewhere else (say, in your table controller's init or loadView methods) and retaining it as an instance variable for later use. Then in sectionIndexTitlesForTableView you only have to return that ivar. If it isn't a property with a retain attribute then make sure you retain it when created so it sticks around (and release it in dealloc).
An easy way to create it is:
self.alphabetIndex = [NSArray arrayWithArray:
[#"A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|#"
componentsSeparatedByString:#"|"]];
The actual letters would have to change depending on the language locale setting but this way it's a bit easier to localize.
You definitely don't want to be creating that temp array each time because it's going to get called a lot.
As far as the index scrolling away it may be related to your returning a new array each time. Try the above first and if it doesn't solve the problem then you may want to tweak the value for the table's sectionIndexMinimumDisplayRowCount property and see if it makes any difference.
I would avoid creating a new NSMutableArray and releasing it every time. Try creating those on viewDidLoad or the class constructor and just reference the pre-built array on sectionIndexTitesForTableView.
If you are not manipulating the array at all, you probably don't need the overhead of an NSMutableArray at all. Try switching it to a plain old NSArray by using the arrayWithObjects static autorelease constructor.
That should speed things up for you.
Make a static variable, it will be released on app exit.
static NSMutableArray* alphabet = nil;
+ (void)initialize {
if(self == [MyViewController class]){
NSUInteger const length = 'Z' - 'A' + 1;
alphabet = [[NSMutableArray alloc] initWithCapacity:length];
for(NSUInteger i=0; i<length; ++i){
unichar chr = 'A' + i;
[alphabet addObject:[NSString stringWithCharacters:&chr length:1]];
}
}
}