Singleton, NSMutableDictionary and plist - objective-c

I have a singleton called SettingsManager in my app that should take care of reading/writing settings to a plist. Singleton is synthesized using macro from Cocoa With Love (zipped macro file). I have only changed retain's return type to (oneway void) from (void). This is due to new compiler in iOS that can take care of memory management. My problem is that whenever i call savePrefs, button calling the selector "hangs" on active state, and sometimes I am getting EXC_BAD_ACCESS. So I guess I failed with memory management. Surprisingly, when no plist file is available (right after app installation), all the defaults are correctly stored and retrieved from my NSMutableDictionary. Below is my code. Will be super grateful for your help.
Martin
CODE:
1/ Singleton header
#import <Foundation/Foundation.h>
#define SALARY_PREF_KEY #"MonthlySalary"
#define DEFAULT_SALARY [NSNumber numberWithDouble: 0.0]
#define CURRENCY_PREF_KEY #"Currency"
#define DEFAULT_CURRENCY #"USD"
#define EXPENSES_PREF_KEY #"Expenses"
#define DEFAULT_EXPENSES [NSNumber numberWithDouble: 0.0]
#define TIME_INTERVAL_PREF_KEY #"TimeInterval"
#define DEFAULT_INTERVAL [NSNumber numberWithInteger: 2]
#define SAVINGS_PREF_KEY #"Savings"
#define DEFAULT_SAVINGS [NSNumber numberWithDouble: 0.0]
#interface SettingsManager : NSObject {
NSString *prefsFilePath;
NSMutableDictionary *settingsDictionary;
NSNumber *salary;
NSString *currency;
NSNumber *expenses;
NSNumber *timeInterval;
NSNumber *savings;
}
+ (SettingsManager *)sharedSettingsManager;
#property (nonatomic, retain) NSString *prefsFilePath;
#property (nonatomic, retain) NSMutableDictionary *settingsDictionary;
#property (nonatomic, retain) NSNumber *salary;
#property (nonatomic, retain) NSString *currency;
#property (nonatomic, retain) NSNumber *expenses;
#property (nonatomic, retain) NSNumber *timeInterval;
#property (nonatomic, retain) NSNumber *savings;
- (void) savePrefs;
#end
2/ Implementation:
#import "SynthesizeSingleton.h"
#import "SettingsManager.h"
#implementation SettingsManager
SYNTHESIZE_SINGLETON_FOR_CLASS(SettingsManager);
#synthesize settingsDictionary,
salary,
currency,
expenses,
timeInterval,
savings,
prefsFilePath;
- (id)init {
self = [super init];
if (self) {
if (prefsFilePath == nil) {
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex: 0];
prefsFilePath = [documentsDirectory stringByAppendingPathComponent:#"iEarn.plist"];
}
if ([[NSFileManager defaultManager] fileExistsAtPath: prefsFilePath]) {
settingsDictionary = [[NSMutableDictionary alloc]
initWithContentsOfFile: prefsFilePath];
}
else {
settingsDictionary = [[NSMutableDictionary alloc] initWithCapacity: 7];
[settingsDictionary setObject: DEFAULT_SALARY forKey: SALARY_PREF_KEY];
[settingsDictionary setObject: DEFAULT_CURRENCY forKey: CURRENCY_PREF_KEY];
[settingsDictionary setObject: DEFAULT_EXPENSES forKey: EXPENSES_PREF_KEY];
[settingsDictionary setObject: DEFAULT_INTERVAL forKey: TIME_INTERVAL_PREF_KEY];
[settingsDictionary setObject: DEFAULT_SAVINGS forKey: SAVINGS_PREF_KEY];
[settingsDictionary writeToFile: prefsFilePath atomically: YES];
}
self.salary = [settingsDictionary objectForKey:SALARY_PREF_KEY];
self.currency = [settingsDictionary objectForKey:CURRENCY_PREF_KEY];
self.expenses = [settingsDictionary objectForKey:EXPENSES_PREF_KEY];
self.timeInterval = [settingsDictionary objectForKey:TIME_INTERVAL_PREF_KEY];
self.savings = [settingsDictionary objectForKey:SAVINGS_PREF_KEY];
}
return self;
}
- (void) savePrefs {
[settingsDictionary setObject: salary forKey: SALARY_PREF_KEY];
[settingsDictionary setObject: currency forKey: CURRENCY_PREF_KEY];
[settingsDictionary setObject: expenses forKey: EXPENSES_PREF_KEY];
[settingsDictionary setObject: timeInterval forKey: TIME_INTERVAL_PREF_KEY];
[settingsDictionary setObject: savings forKey: SAVINGS_PREF_KEY];
[settingsDictionary writeToFile: prefsFilePath atomically: YES];
}
- (void) dealloc {
[settingsDictionary dealloc];
[super dealloc];
}
#end
3/ How I call savePrefs
- (IBAction)saveButtonPressed:(id)sender {
[[SettingsManager sharedSettingsManager] setSalary: [NSNumber numberWithDouble: [salary.text doubleValue]]];
[[SettingsManager sharedSettingsManager] setCurrency: currency.text];
[[SettingsManager sharedSettingsManager] setExpenses: [NSNumber numberWithDouble: [expenses.text doubleValue]]];
[[SettingsManager sharedSettingsManager] setTimeInterval: [NSNumber numberWithInt: [intervalStepper value]]];
[[SettingsManager sharedSettingsManager] setSavings: [NSNumber numberWithDouble: [savings.text doubleValue]]];
[[SettingsManager sharedSettingsManager] savePrefs];
}

It seems that you access directly the prefsFilePath instance variable instead of using its accessor:
prefsFilePath = [documentsDirectory stringByAppendingPathComponent:#"iEarn.plist"];
The value stored is auto-released, so after the current pool is drained, the reference is no longer valid. Instead, you should use:
self.prefsFilePath = [documentsDirectory stringByAppendingPathComponent:#"iEarn.plist"];
or
prefsFilePath = [[documentsDirectory stringByAppendingPathComponent:#"iEarn.plist"] retain];
Note: You may either prefix all the property accesses to avoid problems, or rename the instance variables.

Related

Encode NSMutableArray

EDIT: Ok i decided to save the array in the userDefaults... should be easy, right ?
Save:
NSUserDefaults *userDefs = [NSUserDefaults standardUserDefaults];
[userDefs setObject:videoArray forKey:#"dataArray"];
[userDefs synchronize];
Load:
NSUserDefaults *userDefs = [NSUserDefaults standardUserDefaults];
videoArray = [[NSUserDefaults standardUserDefaults] mutableArrayValueForKey:#"dataArray"];
[tableview reloadData];
NSLog(#"%#",videoArray);
Class of the objects which are in the array:
#interface DEVideoModel : NSObject
#property (copy) NSString *name;
#property (copy) NSImage *thumbnail;
#property (copy) NSDictionary *qualities;
#property (readwrite) float videoSize;
#property (readwrite) float progress;
#property (copy) NSString *filePath;
#property (copy) NSDate *datum;
#end
#synthesize name,filePath,videoSize,qualities,thumbnail,datum,progress;
-(id)init {
self = [super init];
if(self) {
qualities = [[NSDictionary alloc]init];
thumbnail = [[NSImage alloc]init];
}
return self;
}
#end
And my videoArray is (null) when i load it ?! I don't get it. videoArray is a NSMutableArray not NSArray by the way.
IN your code you are writting NSData to NSCoder, so you need to read NSData then convert it to Array.
NSURL *appSupportDir = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:&error];
NSString *path = [NSString stringWithFormat:#"%#/DEConvert.dat",[appSupportDir path]];
NSLog(#"%#",appSupportDir);
NSData *data = [NSData dataWithContentsOfFile:path];
NSMutableArray *arr = [NSKeyedUnarchiver unarchiveObjectWithData:data];
to store object in NSUserDefault
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:arr];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:#"your key"];
Unarchiving is just as easy:
NSData *NewData = [[NSUserDefaults standardUserDefaults] objectForKey:#"your key"];
NSArray *arr = [NSKeyedUnarchiver unarchiveObjectWithData:NewData];

How to Add Multiple Placemarks and Annotations to Map

I have a class that loads a map, get my current location, then does a search on my database for companies in an area based on a zip code radius. I am doing a for loop to loop through each address, forward geocode, now I want to put a placemark and annotation for each location. How can I accomplish this. Here is my code:
- (void)locationUpdate:(CLLocation *)location {
locationLabel.text = [location description];
NSNumber *lat = [[NSString alloc] initWithFormat:#"%g", location.coordinate.latitude];
float latValue = [lat floatValue];
NSNumber *lng = [[NSString alloc] initWithFormat:#"%g", location.coordinate.longitude];
float lngValue = [lng floatValue];
mapView=[[MKMapView alloc] initWithFrame:self.view.bounds];
mapView.showsUserLocation=TRUE;
mapView.mapType=MKMapTypeStandard;
mapView.delegate=self;
/*Region and Zoom*/
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta=0.2;
span.longitudeDelta=0.2;
CLLocationCoordinate2D location1=mapView.userLocation.coordinate;
location1.latitude=latValue;
location1.longitude=lngValue;
region.span=span;
region.center=location1;
/*Geocoder Stuff*/
geoCoder=[[MKReverseGeocoder alloc] initWithCoordinate:location1];
geoCoder.delegate=self;
[geoCoder start];
[mapView setRegion:region animated:TRUE];
[mapView regionThatFits:region];
[self.view insertSubview:mapView atIndex:0];
}
- (void)reverseGeocoder:(MKReverseGeocoder *)geoCoder didFindPlacemark:(MKPlacemark *)placemark
{
NSDictionary *zipDic = [placemark addressDictionary];
NSString *zipCode = [zipDic objectForKey:#"ZIP"];
NSString *post = [NSString stringWithFormat:#"zip=%#", zipCode];
NSString *hostString = #"https://www.mysite.com/searchzip.php?";
// Append string and add percent escapes
hostString = [[hostString stringByAppendingString:post] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *hostURL = [NSURL URLWithString:hostString];
NSString *jsonString = [[NSString alloc] initWithContentsOfURL:hostURL];
self.zipArray = [jsonString JSONValue];
NSLog(#"%#", zipArray);
for (NSString *sZip in zipArray) {
NSString *lblAddress = [sZip objectForKey:#"address"];
NSString *hostStr = [[#"http://maps.google.com/maps/geo?q=" stringByAppendingString:lblAddress]stringByAppendingString:#"&key=ABQIAAAA1KqXKe5yJPkX6ii6Ud K-0RSIvIZDM4KnjydqrehqKK56hFf_fxQc0uyCKoh-4i77-5B0Qfc8Gs223Q&sensor=false&output=json"];
hostStr = [hostStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *hostURL = [NSURL URLWithString:hostStr];
NSString *jsonString = [[NSString alloc] initWithContentsOfURL:hostURL];
SBJSON *parser = [[SBJSON alloc] init];
// parse the JSON string into an object - assuming json_string is a NSString of JSON data
NSArray *object = [parser objectWithString:jsonString error:nil];
NSArray *placemarks = [object objectForKey:#"Placemark"];
NSDictionary *mark = [placemarks objectAtIndex:0];
NSDictionary *point = [mark objectForKey:#"Point"];
NSArray *coordinates = [point objectForKey:#"coordinates"];
NSNumber *lat = (NSNumber*)[coordinates objectAtIndex:0];
float latValue = [lat floatValue];
NSNumber *lon = (NSNumber*)[coordinates objectAtIndex:1];
float lonValue = [lon floatValue];
//Here is where I would put placemarks and annotations
}
}
- (void)locationError:(NSError *)error {
locationLabel.text = [error description];
}
#end
I tried...
CLLocationCoordinate2D location = {latitude: latValue, longitude: lonValue};
return location;
But obviously its wrong.
I tried creating a seperate MapAnnotation class to handle the annotations like so:
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#import "AgencyViewController.h"
#interface MapAnnotation : NSObject<MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *subtitletext;
NSString *titletext;
}
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (readwrite, retain) NSString *titletext;
#property (readwrite, retain) NSString *subtitletext;
-(id)initWithCoordinate:(CLLocationCoordinate2D) coordinate;
- (NSString *)subtitle;
- (NSString *)title;
-(void)setTitle:(NSString*)strTitle;
-(void)setSubTitle:(NSString*)strSubTitle;
and implement it like so:
CLLocationCoordinate2D newCoord = {latitude: latValue, longitude: lonValue};
MapAnnotation *addAnnotation = [[MapAnnotation alloc] initWithCoordinate:newCoord];
[addAnnotation setTitle:#"The Pin Title"];
[addAnnotation setSubTitle:#"The pin subtitle goes here"];
[mapView addAnnotation:addAnnotation];
And that didnt work either...
Figured it out, needed to add
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
MKPinAnnotationView *pinView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:#"Prospects"];
if(pinView == nil) {
pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"Prospects"];
pinView.pinColor = MKPinAnnotationColorGreen;
pinView.animatesDrop = NO;
pinView.canShowCallout = YES;
} else {
pinView.annotation = annotation;
}
return pinView;
}
Now I need to figure out how to change the color of my location pin.

XML Parsing Class Leaking Strings on Rerun

I've been at this issue for two days, and no matter what I do, I cannot get it to stop leaking strings.
The class is a XML parser (using TouchXML), that is designed to run repeatedly throughout the life time of the application. The first time it runs, there are no leaks, everything cleans up perfectly. On the second run, it begins to leaks, almost always where ever strings are.
Some images from Instruments:
http://www.producerstudio.net/1.png
http://www.producerstudio.net/2.png
.h
#import <Foundation/Foundation.h>
#import "TouchXML.h"
#protocol RSSParsingComplete
-(void)parsingFinished;
#end
#interface RSS : NSObject<NSXMLParserDelegate>{
NSArray *rssURLArray;
NSMutableData *xmlData;
NSMutableArray *articles;
NSMutableArray *arrayOfArticles;
int numberOfFeeds;
NSDateFormatter *inputFormatter;
NSDateFormatter *outputFormatter;
id<RSSParsingComplete> delegate;
}
#property (nonatomic, retain) NSArray *rssURLArray;
#property (nonatomic, retain) NSMutableData *xmlData;
#property (nonatomic, retain) id<RSSParsingComplete> delegate;
#property (nonatomic, retain) NSMutableArray *articles;
#property (nonatomic, retain) NSMutableArray *arrayOfArticles;
#property (nonatomic, retain) NSDateFormatter *inputFormatter;
#property (nonatomic, retain) NSDateFormatter *outputFormatter;
-(id)initWithRSSArray:(NSArray *)inputURLArray;
-(void)connect;
-(NSArray *)feedArticles;
#end
.m
#import "RSS.h"
#implementation RSS
#synthesize xmlData, rssURLArray, articles, arrayOfArticles, delegate, inputFormatter, outputFormatter;
-(void)connect{
self.xmlData = [[[NSMutableData alloc] init] autorelease];
NSURL *rssURL = [[NSURL alloc] initWithString:[self.rssURLArray objectAtIndex:numberOfFeeds-1]];
NSURLConnection *urlConnection = [[NSURLConnection alloc] initWithRequest:[NSURLRequest requestWithURL:rssURL] delegate:self];
[urlConnection release];
[rssURL release];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
[self.xmlData setLength:0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[self.xmlData appendData:data];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
[xmlData release];
[connection release];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
CXMLDocument *xmlDoc = [[[CXMLDocument alloc] initWithData:xmlData options:0 error:nil] autorelease];
self.articles = [[[NSMutableArray alloc] init] autorelease];
self.inputFormatter = [[[NSDateFormatter alloc] init] autorelease];
self.outputFormatter = [[[NSDateFormatter alloc] init] autorelease];
[self.inputFormatter setDateFormat:#"EEE, dd MMM yyyy HH:mm:ss zzz"];
[self.inputFormatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"] autorelease]];
[self.inputFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"UTC"]];
[self.outputFormatter setDateFormat:#"dd.MM.yyyy HH:mm:ss"];
[self.outputFormatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"] autorelease]];
[self.outputFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"UTC"]];
NSArray *itemNodes = [xmlDoc nodesForXPath:#"//item" error:nil];
for(CXMLElement *node in itemNodes){
NSMutableDictionary *article = [[NSMutableDictionary alloc] init];
for(int counter = 0; counter < [node childCount]; counter++){
if([[[node childAtIndex:counter] name] isEqualToString:#"title"]){
[article setObject:[[node childAtIndex:counter] stringValue] forKey:#"title"];
}
if([[[node childAtIndex:counter] name] isEqualToString:#"link"]){
[article setObject:[[node childAtIndex:counter] stringValue] forKey:#"url"];
}
if([[[node childAtIndex:counter] name] isEqualToString:#"description"]){
[article setObject:[[node childAtIndex:counter] stringValue] forKey:#"description"];
}
if([[[node childAtIndex:counter] name] isEqualToString:#"pubDate"]){
NSDate *tempDate = [self.inputFormatter dateFromString:[[node childAtIndex:counter] stringValue]];
[article setObject:[self.outputFormatter stringFromDate:tempDate] forKey:#"name"];
}
}
[self.articles addObject:article];
[article release];
}
NSArray *feedTitleNode = [xmlDoc nodesForXPath:#"//title" error:nil];
NSString *feedTitle = [[NSString alloc] initWithString:[[[feedTitleNode objectAtIndex:0] childAtIndex:0] stringValue]];
[self.articles addObject:feedTitle];
[feedTitle release];
[self.arrayOfArticles addObject:[articles copy]];
[self.articles removeAllObjects];
[inputFormatter release];
[outputFormatter release];
numberOfFeeds--;
if(numberOfFeeds > 0){
[self connect];
}else{
[delegate parsingFinished];
}
}
-(NSArray *)feedArticles{
NSLog(#"Array of Articles: %#", self.arrayOfArticles);
return self.arrayOfArticles;
}
-(id)initWithRSSArray:(NSArray *)inputURLArray{
self = [super init];
if (self) {
self.arrayOfArticles = [[[NSMutableArray alloc] init] autorelease];
self.rssURLArray = [[[NSArray alloc] initWithArray:inputURLArray] autorelease];
numberOfFeeds = [self.rssURLArray count];
[self connect];
}
return self;
}
-(void)dealloc{
[rssURLArray release];
[xmlData release];
[articles release];
[arrayOfArticles release];
[super dealloc];
}
- (id)init
{
self = [super init];
return self;
}
#end
I've done everything I can think of to resolve the leaks. I've read the Apple Memory Management guides, as well as the excellent guide on iPhoneDevSDK and that has helped me cut down on 90% of the leaks I originally had (the class doesn't leak so long as you call it once). Maybe i've been staring at this for too long, or maybe i'm missing something obvious.
I appreciate it!
First, should delegate be retained? I'm not sure why you need it as an instance variable at all. But since it's retained (and you don't seem to release it), your RSS object will retain a circular reference to itself and won't ever be released.
Second, do you need to keep the date formatters in an instance variable? It looks like you're allocating them and releasing them in the same method. Note that they're retained in the RSS instance and never released.

Memory Leak from NSMutableArray and NSDictionary

I have a memomry leak problem, maybe somebody can help me.
I try to load an NSMutable array for a pList and show some elements in a TablevView
In the h.File I declare
#interface Bestellung : UIViewController <UITableViewDelegate, UITableViewDelegate> {
NSMutableArray *bestellteVorspeisen;
NSMutableArray *bestellteVorspeisenPreis;
NSMutableArray *bestellteVorspeisenDetails;
NSMutableArray *bestellteVorspeisenBild;
NSMutableArray *bestellteVorspeisenNummer;
NSMutableArray *bestellListe;
IBOutlet UITableView *myTable;
}
#property (nonatomic, retain) NSMutableArray *bestellListe;
#property (nonatomic,retain) NSMutableArray *bestellteVorspeisen;
#property (nonatomic,retain) NSMutableArray *bestellteVorspeisenPreis;
#property (nonatomic,retain) NSMutableArray *bestellteVorspeisenDetails;
#property (nonatomic,retain) NSMutableArray *bestellteVorspeisenBild;
#property (nonatomic,retain) NSMutableArray *bestellteVorspeisenNummer;
#end
In the M.File viewDidLoad I load the pList in bestellListe
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"Bestellung.plist"];
success = [fileManager fileExistsAtPath:filePath];
if (!success)
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"Bestellung" ofType:#"plist"];
success = [fileManager copyItemAtPath:path toPath:filePath error:&error];
}
self.bestellListe = [[NSMutableArray alloc] initWithContentsOfFile:filePath];
Then I generate the MutableArray
bestellteVorspeisen = [[NSMutableArray alloc] initWithCapacity:1];
bestellteVorspeisenPreis = [[NSMutableArray alloc] initWithCapacity:1];
bestellteVorspeisenDetails = [[NSMutableArray alloc] initWithCapacity:1];
bestellteVorspeisenBild = [[NSMutableArray alloc] initWithCapacity:1];
bestellteVorspeisenNummer = [[NSMutableArray alloc] initWithCapacity:1];
Afterwards I fill them from bestellListe
for (NSDictionary *bestellDict in bestellListe)
{ if ([[bestellDict objectForKey:#"Tisch"] isEqualToString:
[NSString stringWithFormat:#"%i",TischNummer]])
{if ([[bestellDict objectForKey: kBestellungKategorieString] isEqualToString: #"Vorspeise"])
[bestellteVorspeisen addObject: [bestellDict objectForKey:kBestellungNameString]];
[bestellteVorspeisenPreis addObject: [bestellDict objectForKey:kBestellungPreisString]];
[bestellteVorspeisenDetails addObject: [bestellDict objectForKey:kBestellungDetailString]];
[bestellteVorspeisenBild addObject: [bestellDict objectForKey:kBestellungBildString]];
[bestellteVorspeisenNummer addObject: [bestellDict objectForKey:kBestellungNummer]];
} // if
} // if
} // for
This causes memoryleaks at
self.bestellListe = [[NSMutableArray alloc] initWithContentsOfFile:filePath];
and
bestellteVorspeisen = [[NSMutableArray alloc] initWithCapacity:1];
bestellteVorspeisenPreis = [[NSMutableArray alloc] initWithCapacity:1];
bestellteVorspeisenDetails = [[NSMutableArray alloc] initWithCapacity:1];
bestellteVorspeisenBild = [[NSMutableArray alloc] initWithCapacity:1];
bestellteVorspeisenNummer = [[NSMutableArray alloc] initWithCapacity:1];
Here ist dealloc
- (void)dealloc {
NSLog(#"Bestellung dealloziert");
[bestellteVorspeisen release];
[bestellteVorspeisenPreis release];
[bestellteVorspeisenDetails release];
[bestellteVorspeisenBild release];
[bestellteVorspeisenNummer release];
[bestellListe release];
[myTable release];
[super dealloc];
Can somebody give me some help, I'm really new in that.
your property synthesized method automatically retains received objects :
#property (nonatomic, retain) NSMutableArray *bestellListe;
So when you do :
self.bestellListe = [[NSMutableArray alloc] initWithContentsOfFile:filePath];
Your bestellListe has a retain count of 2 (the alloc + the retain from the property).
On your dealloc you only release it once :
[bestellListe release];
The simpler solution seems to retain it only once when creating it, with an autoreleased initializer like :
self.bestellListe = [NSMutableArray arrayWithContentsOfFile:filePath];
Hope this can help

objective-c cant find memory leak

im mapping an xml on a custom nsobject.
when the user hits reload the function is called again.
i get several memory leaks on all strings:
UPDATE this is the current code.
- (void)mapDataOnModel
{
if(mixesArr != nil)
{
//[mixesArr release];
[mixesArr removeAllObjects];
[playListArr removeAllObjects];
}
else
{
mixesArr = [[NSMutableArray alloc]init];
playListArr = [[NSMutableArray alloc] init];
}
MixVO *tmpMix;
AudioVO *tmpAudio;
for (DDXMLElement *node in nodes)
{
tmpMix = [[MixVO alloc] init];
tmpMix.uuid = [[node attributeForName:#"uuid"] stringValue];
tmpMix.name = [[[node elementsForName:#"name"] objectAtIndex:0] stringValue];
tmpMix.artist = [[[node elementsForName:#"artist"] objectAtIndex:0] stringValue];
tmpMix.path = [[[node elementsForName:#"file"] objectAtIndex:0] stringValue];
tmpMix.headline = [[[node elementsForName:#"headline"] objectAtIndex:0] stringValue];
tmpMix.teaser = [[[node elementsForName:#"teaser"] objectAtIndex:0] stringValue];
tmpMix.copy = [[[node elementsForName:#"copy"] objectAtIndex:0] stringValue];
tmpMix.isHighlight = NO;
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"HH:mm:ss"];
tmpMix.duration = [dateFormat dateFromString:[[[node elementsForName:#"duration"] objectAtIndex:0] stringValue]] ;
[dateFormat release];
// CHECK IF IT IS A HIGHLIGHT MIX
for (int i = 0; i < [[highlightsNode elementsForName:#"member"] count]; i++)
{
NSString *highlightID;
highlightID = [[[highlightsNode elementsForName:#"member"] objectAtIndex:i] stringValue] ;
if([tmpMix.uuid isEqualToString:highlightID])
{
tmpMix.isHighlight = YES;
}
}
if([[node elementsForName:#"image_standard"] count] > 0)
tmpMix.image_standard = [[[node elementsForName:#"image_standard"] objectAtIndex:0] stringValue] ;
if([[node elementsForName:#"image_artist"] count] > 0)
tmpMix.image_artist = [[[node elementsForName:#"image_artist"] objectAtIndex:0] stringValue] ;
if([[node elementsForName:#"image_teaser"] count] > 0)
tmpMix.image_teaser = [[[node elementsForName:#"image_teaser"] objectAtIndex:0] stringValue] ;
if([[node elementsForName:#"image_player"] count] > 0)
tmpMix.image_player = [[[node elementsForName:#"image_player"] objectAtIndex:0] stringValue] ;
/*
tmpAudio = [[AudioVO alloc] init];
tmpAudio.file = tmpMix.path;
NSString *tmpDuration;
tmpDuration = [[[node elementsForName:#"duration"] objectAtIndex:0] stringValue];
tmpAudio.duration = tmpDuration;
// PARSE TRACKS
NSArray *track = NULL;
track = [node elementsForName:#"tracks"];
DDXMLElement *trackElems = [track objectAtIndex:0];
NSArray *tracks = NULL;
tracks = [trackElems elementsForName:#"track"];
NSMutableArray *tracksArray;
tracksArray = [[NSMutableArray alloc]init];
TrackVO *tmpTrack;
for (DDXMLElement *node2 in tracks)
{
tmpTrack = [[TrackVO alloc] init];
tmpTrack.timecode = [[node2 attributeForName:#"timecode"] stringValue];
tmpTrack.name = [node2 stringValue];
[tracksArray addObject:tmpTrack];
[tmpTrack release];
}
tmpAudio.tracksArr = tracksArray;
[tracksArray release];
tmpMix.audioVO = tmpAudio;
[tmpAudio release];
*/
[mixesArr addObject:tmpMix];
[tmpMix release];
}
// SORT PROGRAMM
/*
NSSortDescriptor *lastDescriptor =
[[[NSSortDescriptor alloc]
initWithKey:#"artist"
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)] autorelease];
NSArray * descriptors =
[NSArray arrayWithObjects:lastDescriptor, nil];
NSArray * sortedArray = [mixesArr sortedArrayUsingDescriptors:descriptors];
//[mixesArr release];
mixesArr = [[NSMutableArray alloc]initWithArray:sortedArray];
// PARSE PLAYLIST
for (DDXMLElement *node in nodesPl)
{
SchedVO *tmpSched;
tmpSched = [[SchedVO alloc] init];
NSString *timeStr;
timeStr = [[node attributeForName:#"timestamp"] stringValue];
tmpSched.date = [NSDate dateWithTimeIntervalSince1970:timeStr.intValue];
tmpSched.uid = [node stringValue];
[playListArr addObject:tmpSched];
//[tmpSched release];
}
*/
[self updateDone];
}
MixVO:
#interface MixVO : NSObject
{
NSString *uuid;
NSString *name;
NSString *artist;
NSString *path;
NSString *headline;
NSString *teaser;
NSString *copy;
NSString *image_standard;
NSString *image_artist;
NSString *image_teaser;
NSString *image_player;
NSDate *duration;
AudioVO *audioVO;
BOOL isHighlight;
}
#property (nonatomic,retain) NSString *uuid;
#property (nonatomic,retain) NSString *name;
#property (nonatomic,retain) NSString *artist;
#property (nonatomic,retain) NSString *path;
#property (nonatomic,retain) NSString *headline;
#property (nonatomic,retain) NSString *teaser;
#property (nonatomic,retain) NSString *copy;
#property (nonatomic,retain) NSString *image_standard;
#property (nonatomic,retain) NSString *image_artist;
#property (nonatomic,retain) NSString *image_teaser;
#property (nonatomic,retain) NSString *image_player;
#property (nonatomic,retain) NSDate *duration;
#property (nonatomic,retain) AudioVO *audioVO;
#property BOOL isHighlight;
#end
maybe someone can help me with this.
thanks in advance
alex
if(mixesArr != nil)
{
[mixesArr removeAllObjects];
[playListArr removeAllObjects];
}
mixesArr = [[NSMutableArray alloc]init];
This suggest mixesArr could already be allocated, and you simply allocate a new instance, making the original mixesArr a dangling pointer.
Shouldn't you write something like:
if(mixesArr != nil)
{
[mixesArr removeAllObjects];
[playListArr removeAllObjects];
}
else {
mixesArr = [[NSMutableArray alloc]init];
}
Or something similar?
Where are you releasing mixesArr?
You'll also want to release all the strings you're retaining.