Memory leaks when deleting row from a tableview - iphone

I am loading data from a plist into a tableview in my application. Data is stored in a mutable dictionary of mutable dictionaries.
Here is my viewDidLoad method:
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Categories";
// load data from plist fle
self.categories = [[[NSMutableDictionary alloc] initWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:#"InventoryItems" ofType:#"plist"]] autorelease];
// add buttons to navigation menu
self.navigationItem.rightBarButtonItem = self.editButtonItem;
self.navigationItem.leftBarButtonItem = self.addButton;
}
My tableview is editable, so user can delete categories. In my commitEditingStyle:forRowAtIndexPath: method I update my data model:
[self.categories removeObjectForKey: [[self.categories allKeys] objectAtIndex:indexPath.row]];
When I profile my app it leaks memory. I am not very proficient in using the profile tool, but it seems to find leaks in my categories dictionary every time I delete a row.
I wonder where I missed releasing something? Is it a problem that object I am removing is a dictionary as well and I need to remove its objects too?

This leaks (if the property is retain or copy):
self.categories = [[NSMutableDictionary alloc] initWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:#"InventoryItems" ofType:#"plist"]];
Use this instead:
categories = [[NSMutableDictionary alloc] initWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:#"InventoryItems" ofType:#"plist"]];
or this:
self.categories = [[[NSMutableDictionary alloc] initWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:#"InventoryItems" ofType:#"plist"]] autorelease];

I wonder if this would give you anything different?
NSMutableDictionary *d = [[NSMutableDictionary alloc] initWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:#"InventoryItems" ofType:#"plist"]];
self.categories = d;
[d release];

Related

NSMutableDictionary not working in voids and IBActions

I created an NSMutableDictionary called *temp in my .h file of the main viewController, and added this code to bring in the information from my .plist file.
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle] pathForResource:#"Data" ofType:#"plist"];
temp=[NSMutableDictionary dictionaryWithContentsOfFile:path];
}
In the same view controller, I added a button action and added the following code:
-(IBAction)mathButton:(UIButton *)_sender
{
label1.text = [temp objectForKey:#"m1name"];
}
Where "label1 is a text field in the .xib, and m1name is one of the keys in the .plist
But when I run it, it doesn't work, and highlights label1.text = [temp objectForKey:#"m1name"]; and calls it bad access.
I've been stuck on this for a couple of days, and tried lots of things. An answer would be really helpful.
Thanks
temp=[NSMutableDictionary dictionaryWithContentsOfFile:path];
You're not retaining the dictionary created via dictionaryWithContentsOfFile:path. You should either change that line to:
temp = [[NSMutableDictionary dictionaryWithContentsOfFile:path] retain];
(and make sure it's released in dealloc), or, if temp is a property, set it via
self.temp = [NSMutableDictionary dictionaryWithContentsOfFile:path];
In .h:
#interface ...
{
NSMutableDictionary* temp;
}
In .m:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString* path = [[NSBundle mainBundle] pathForResource: #"Data"
ofType: #"plist"];
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath: path];
if (exists)
{
temp = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
NSLog(#"%#", [temp description]);
}
}
- (IBAction) mathButton: (UIButton *)_sender
{
label1.text = [temp objectForKey: #"m1name"];
}
If MRC:
- (void) dealloc
{
[temp release];
[super dealloc];
}

Instance Variable not allocating in memory

I'm having an NSObject class where i have an init method defined something like below,
- (id)initWithPlistName:(NSString *)plistFileName{
if (self = [super init]) {
plistName = plistFileName;
plistContent = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle]
pathForResource:plistName ofType:#"plist"]]; // this plistContent array is not allocating in memory
}
return self;
}
I'm calling this method in my applications AppDelegate Class didFinishLaunchingWithOptions method, plistContent is my iVar of type NSArray but whenever control comes to plistContent alloc init line and while returning self, there is no memory allocated for my array.
What may be the problem happening here, Any help is appreciated in advance.
I suppose you have not changed the Datatype of your plist root key in your plist flie from dictionary to array
Check file exists:
NSString *path = [[NSBundle mainBundle] pathForResource:plistName ofType:#"plist"];
if(path)
{
plistContent = [[NSArray alloc] initWithContentsOfFile:path];
}
else
{
NSLog(#"File Not exists");
}
Try this
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"plistName" ofType:#"plist"];
NSDictionary *myDict = [[NSDictionary alloc] initWithContentsOfFile:filePath];
NSArray *array = [NSArray arrayWithArray:[myDict objectForKey:#"Root"]];

MWPhotoBrowser add data from plist?

trying to get some data from a plist into the MWPhotoBrowser sample app.
Any ideas how to do it?
UIViewController *converterController = nil;
NSMutableArray *photos = [[NSMutableArray alloc] init];
converterController = [[MWPhotoBrowser alloc] initWithPhotos:photos];
converterController.hidesBottomBarWhenPushed = YES;
//here individual images can be added. However need to add images from a plist.
[photos addObject:[MWPhoto photoWithFilePath:[[NSBundle mainBundle] pathForResource:#"image1" ofType:#"jpg"]]];
[photos addObject:[MWPhoto photoWithFilePath:[[NSBundle mainBundle] pathForResource:#"image2" ofType:#"jpg"]]];
[photos addObject:[MWPhoto photoWithFilePath:[[NSBundle mainBundle] pathForResource:#"image3" ofType:#"jpg"]]];
[photos addObject:[MWPhoto photoWithFilePath:[[NSBundle mainBundle] pathForResource:#"image4" ofType:#"jpg"]]];
if (converterController) {
[self.navigationController pushViewController:converterController animated:YES];
[converterController release];
}
[photos release];
Can add objects individually as shown above, but not able to do it with a plist.
Can anyone share an idea?
thanks
w
ell i got this but it doesnt work.
SString *path = [[NSBundle mainBundle] pathForResource:
#"ImageData" ofType:#"plist"];
// Build the array from the plist
photos = [[NSMutableArray alloc] initWithContentsOfFile:path];
crashes the app.
I must use the MWPhoto property.
Help anyone?
Maybe Michael Waterfall wants to look into this?
EDIT:
OK here is the working code (well it works ok so far)
NSUInteger nimages = 0;
for (; ; nimages++) {
NSString *nameOfImage_ = #"imageSufix";
NSString *imageName = [NSString stringWithFormat:#"%#%d.jpg", nameOfImage_, (nimages + 1)];
//NSLog(#"Name is %#", imageName); log the names
image = [UIImage imageNamed:imageName];
if (image == nil) {
break;
}
[photos addObject:[MWPhoto photoWithImage:image]];

Instruments Leaks tells about a memory leak when initializing object

Can anyone please tell me why the following code leaks? Instruments tells me about 2 leaks. The 2 lines that obviously cause the leak are:
Person *pers = [[Person alloc] init];
and
NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
The whole is listed below:
PersonViewController *personenDatenController = [[PersonViewController alloc]
initWithStyle:UITableViewStyleGrouped];
personenDatenController.view.backgroundColor = [UIColor clearColor];
Person *pers = [[Person alloc] init];
NSString *path = [[self class] pathForDocumentWithName:#"Person.plist"];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:path];
if (!fileExists) {
NSLog(#"file does not exist yet");
NSString *content = #"";
NSData *fileContents = [content dataUsingEncoding:NSUTF8StringEncoding];
[[NSFileManager defaultManager] createFileAtPath:path
contents:fileContents
attributes:nil];
}
NSMutableDictionary *dict = [[NSMutableDictionary alloc]
initWithContentsOfFile:path];
[pers setVorName:[dict valueForKey:#"vorName"]];
[pers setNachName:[dict valueForKey:#"nachName"]];
[pers setStrassenName:[dict valueForKey:#"strassenName"]];
[pers setHausNummer:[dict valueForKey:#"hausNummer"]];
[pers setPlz:[dict valueForKey:#"plz"]];
[pers setStadt:[dict valueForKey:#"stadt"]];
[pers setHandyNummer:(NSInteger*)[dict valueForKey:#"handyNummer"]];
[pers setEmail:[dict valueForKey:#"email"]];
[pers setSteuerSatz:[[dict valueForKey:#"steuerSatz"] floatValue]];
[dict release];
[personenDatenController setPerson:pers];
[navigationController pushViewController:personenDatenController animated:YES];
[personenDatenController release];
[pers release];
The variable "path" comes from the following static method:
+ (NSString *)pathForDocumentWithName:(NSString *)documentName
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *tempPath = [documentsDirectory stringByAppendingPathComponent:documentName];
return tempPath;
}
Thanks in advance for your help!
Kind regards
Phil
Assuming that setPerson calls retain on pers. Does your PersonViewController dealloc, call release on that person object? If so, put a breakpoint there (or NSLog) and find out the retainCount of the person. If it's not going to 0, where else might you have retained it?
Thank you guys for your responses.
PersonViewController does retain the person object but I put a release for the person object in dealloc. The retaincount is okay.
I moved the initialization of the Person object to the PersonViewController and now everything is fine. This seems quite strange to me.
Thank you
Regards

Problem removing multiple objects from NSMutableArray iPhone SDK

I am having trouble removing objects from nsmutable array. Here it is.
NSURL *url = [NSURL URLWithString:#"http://www.lockerz.com/dailies"]];
NSData *datadata = [NSData dataWithContentsOfURL:url];
NSString *removeForArray = [[NSString alloc] initWithData:datadata encoding:NSASCIIStringEncoding];
NSArray *theArray = [removeForArray componentsSeparatedByString:#" "];
NSMutableArray *deArray = [[NSMutableArray array] initWithArray:theArray];
[deArray removeObjectsInRange:NSMakeRange(0, 40)];
NSLog(#"%#", deArray);
+[NSMutableArray array] already returns an initialized array. Don't use an initializer method on that, they are used on new instances that you allocd.
In this case you can either
alloc/init an instance
use -mutableCopy
use a suitable convenience constructor
The three following lines are equivalent:
NSMutableArray *a = [[theArray mutableCopy] autorelease];
NSMutableArray *b = [NSMutableArray arrayWithArray:theArray];
NSMutableArray *c = [[[NSMutableArray alloc] initWithArray:theArray] autorelease];