Instance Variable not allocating in memory - iphone

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"]];

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

Why is my NSMutableDictionary null?

Here's my delegate method for UIAlertView. I have no idea why myWordsDictionary is null when running the app. (Note: _dailyWords is an NSDictionary object and bookmarked is an NSString object.)
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex != [alertView cancelButtonIndex]) {
NSLog(#"Clicked button index !=0");
// Add the action here
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *myWordsPath = [documentPath stringByAppendingPathComponent:#"MyWords.plist"];
NSMutableDictionary *myWordsDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:myWordsPath];
[myWordsDictionary setValue:[_dailyWords objectForKey:bookmarked] forKey:bookmarked];
[myWordsDictionary writeToFile:myWordsPath atomically:YES];
NSLog(#"%#", [myWordsDictionary description]);
[myWordsDictionary release];
} else {
NSLog(#"Clicked button index = 0");
// Add another action here
}
}
Thanks in advance.
myWordsPath may not contain any valid file, and you are initializing your NSMutableDictionary from content of the the file present at that path. That's why you are getting a null dictionary.
First, try check myWordsPath, if it returns null, you should look and find correct path.
Second, how you generate your plist? MyWords.plist must contain valid format. If you unsure, you should create from within XCode, there is plist object.
NSBundle *bundle = [NSBundle mainBundle];
NSString *plistPath = [bundle pathForResource:
#"MyWords" ofType:#"plist"];
NSDictionary *dictionary = [[NSDictionary alloc]
initWithContentsOfFile:plistPath];
please try this code..
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
documentPath = [documentPath stringByAppendingPathComponent:#"MyWords.plist"];
NSMutableDictionary *myWordsDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:documentPath];

Help with Memory leak: init NSMutableArray from file

In some point in my app, I need to load a list from a file, so I implement this method to load the list:
-(void)loadList
{
NSString *filePath = [self dataFilePath]; //This is a method return the path of file
if([[NSFileManager defaultManager] fileExistsAtPath:filePath])
{
NSMutableArray *tempArray = [[NSMutableArray alloc]initWithContentsOfFile:filePath];
self.list = [[NSMutableArray alloc]initWithArray:tempArray];
[tempArray release];
}
}
The self.list is a (retain) property.
I think the leak is from [alloc] when I init the selfl.list. I used
self.list = [[[NSMutableArray alloc]initWithArray:tempArray]autorelease];
But the app crashes due to EXC_BAD_ACCESS. So I am confused here how to solve this.
Thanks for any suggestions.
Just assign,
self.list = tempArray;
As tempArray is already an array, you don't have to create another array from it. You ca directly assign to self.list.
There is no need to allocate another time for array .So just assign directly
-(void)loadList
{
NSString *filePath = [self dataFilePath]; //This is a method return the path of file
if([[NSFileManager defaultManager] fileExistsAtPath:filePath])
{
NSMutableArray *tempArray = [[NSMutableArray alloc]initWithContentsOfFile:filePath];
self.list = [tempArray copy];
[tempArray release];
}
}
Don't autorelease it. (I guess).
is your list property assign or retain?
if it is retain, then you should change this:
self.list = [[NSMutableArray alloc]initWithArray:tempArray];
to this:
self.list = [[NSMutableArray arrayWithArray:tempArray];

Memory leaks when deleting row from a tableview

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

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