Class with memory leaks in instruments - ios

I have a couple of classes which functions are execute SQL statements against a WEB service in order to get or set data in the database.
Works fine, but the problem is when I'm testing in instruments/leaks the 90% of the leaks are because these classes.
Could you tell me what I'm loosing?
Thanks.
Here is the code:
Where the data is stored:
.h
#interface iSQLResult : NSObject {
NSMutableArray *Records;
}
#property (nonatomic, assign) int CountX;
#property (nonatomic, assign) int CountY;
#property (nonatomic, retain) NSMutableArray *Columns;
#property (nonatomic, retain) NSMutableArray *Records;
#property (nonatomic, retain) NSMutableArray *FieldsNames;
#property (nonatomic, assign) int ErrorCode;
#property (nonatomic, retain) NSString *ErrorDescription;
-(void)addField:(NSString*)fieldName;
-(void)addRecord:(NSMutableArray*)items;
-(NSMutableArray *)getRecord:(int)y;
-(NSString*)getValue:(int) x posY:(int) y;
-(NSString*)getValueByName:(NSString *) colName posY:(int) y;
-(void)setValueByName:(NSString *) colName posY:(int) y value:(NSString *)value;
-(id) copyWithZone: (NSZone *) zone;
#end
.m
#import "iSQLResult.h"
#import <stdarg.h>
#implementation iSQLResult
#synthesize CountX;
#synthesize CountY;
#synthesize Columns;
#synthesize Records;
#synthesize FieldsNames;
#synthesize ErrorCode;
#synthesize ErrorDescription;
-(id)init
{
self = [super init];
if (self)
{
self.CountX =0;
self.CountY =0;
self.ErrorCode = 0;
self.ErrorDescription = #"";
self.FieldsNames = [NSMutableArray array];
self.Columns = [NSMutableArray array];
self.Records = [NSMutableArray array];
}
return self;
}
-(void)removeRecord:(int)index
{
[self.Records removeObjectAtIndex:index];
self.CountY = self.CountY - 1;
}
-(void)addField:(NSString*)fieldName
{
[self.FieldsNames addObject:[NSString stringWithFormat:#"%#", fieldName]];
self.CountX = self.CountX +1;
}
-(void)addRecord:(NSMutableArray*)items
{
[self.Records addObject:items];
self.CountY = self.CountY +1;
}
-(NSMutableArray *)getRecord:(int)y
{
return [Records objectAtIndex:y];
}
-(NSString *)getValue:(int) x posY:(int)y
{
return [[NSString stringWithFormat:#"%#", [[Records objectAtIndex:y] objectAtIndex:x]] copy];
}
-(NSString*)getValueByName:(NSString *) colName posY:(int) y
{
int a=0;
for (a=0;a<CountX;a++)
{
if ([[colName uppercaseString] isEqualToString:[[FieldsNames objectAtIndex:a] uppercaseString]])
{
return [[NSString stringWithFormat:#"%#", [[Records objectAtIndex:y] objectAtIndex:a]] copy];
}
}
return #"";
}
-(void)setValueByName:(NSString *) colName posY:(int) y value:(NSString *)value
{
int a=0;
for (a=0;a<CountX;a++)
{
if ([[colName uppercaseString] isEqualToString:[[FieldsNames objectAtIndex:a] uppercaseString]])
{
[[Records objectAtIndex:y] replaceObjectAtIndex:a withObject:value];
}
}
}
-(void)dealloc
{
[Columns release];
[Records release];
[FieldsNames release];
[ErrorDescription release];
[super dealloc];
}
-(id) copyWithZone: (NSZone *) zone
{
iSQLResult *SQLRCopy = [[iSQLResult allocWithZone: zone] init];
[SQLRCopy setCountX:self.CountX];
[SQLRCopy setCountY:self.CountY];
[SQLRCopy setRecords:[self.Records mutableCopyWithZone:zone]];
[SQLRCopy setColumns:[self.Columns mutableCopyWithZone:zone]];
[SQLRCopy setFieldsNames:[self.FieldsNames mutableCopyWithZone:zone]];
[SQLRCopy setErrorCode:self.ErrorCode];
[SQLRCopy setErrorDescription:[self.ErrorDescription copyWithZone:zone]];
return SQLRCopy;
}
#end
The class who ask for the data to the web service comunication class and gets a xml structure:
.h
#import <Foundation/Foundation.h>
#import "iSQLResult.h"
#import "IM2_WebServiceComm.h"
#interface iSQL : NSObject <NSXMLParserDelegate> {
iSQLResult *SQLR;
IM2_WebServiceComm * WSC;
NSXMLParser *xmlParser;
BOOL Found;
BOOL FieldsReaded;
BOOL loadFieldsNow;
BOOL loadErrNumNow;
BOOL loadErrDesNow;
NSString *chunksString;
NSMutableArray *tempRecord;
}
#property (nonatomic, retain) NSString *URLConnection;
-(void)SQLReader:(NSString*)SQLString;
-(void)SQLExec:(NSString*)SQLString;
-(void)setURLConnection:(NSString *) WebSURL;
-(iSQLResult*) getSQLR;
-(void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName;
-(void) parser:(NSXMLParser *) parser foundCharacters:(NSString *)string;
-(void) parser:(NSXMLParser *) parser didStartElement:(NSString *) elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *) qName attributes:(NSDictionary *) attributeDict;
#end
.m
#import "iSQL.h"
#implementation iSQL
#synthesize URLConnection;
- (iSQLResult*)getSQLR
{
return [SQLR copy];
}
-(void)SQLExec:(NSString*)SQLString
{
FieldsReaded = NO;
Found = NO;
loadFieldsNow = NO;
if (SQLR)
{
[SQLR release];
SQLR = nil;
}
SQLR = [[iSQLResult alloc] init];
WSC = [[IM2_WebServiceComm alloc] init];
[WSC setURL:URLConnection];
NSString *theXML = [WSC callMethod:#"ExecNonQuery" sendInstruction:SQLString];
#try
{
xmlParser = [[NSXMLParser alloc] initWithData:[theXML dataUsingEncoding:NSUTF8StringEncoding]];
[xmlParser setDelegate: self];
[xmlParser setShouldResolveExternalEntities:NO];
if(![xmlParser parse])
{
NSLog(#"ERROR PARSING");
}
[xmlParser release];
}
#catch(NSException * ex)
{
NSLog(#"%#",[[ex reason] UTF8String]);
}
[WSC release];
}
-(void)SQLReader:(NSString*)SQLString
{
FieldsReaded = NO;
Found = NO;
loadFieldsNow = NO;
if (SQLR)
{
[SQLR release];
SQLR = nil;
}
SQLR = [[iSQLResult alloc] init];
WSC = [[IM2_WebServiceComm alloc] init];
[WSC setURL:URLConnection];
NSString *theXML = [WSC callMethod:#"ExecSQL" sendInstruction:SQLString];
#try
{
xmlParser = [[NSXMLParser alloc] initWithData:[theXML dataUsingEncoding:NSUTF8StringEncoding]];
[xmlParser setDelegate: self];
[xmlParser setShouldResolveExternalEntities:NO];
if(![xmlParser parse])
{
NSLog(#"ERROR PARSING");
}
[xmlParser release];
}
#catch(NSException * ex)
{
NSLog([NSString stringWithFormat:#"%#",[[ex reason] UTF8String]]);
}
[WSC release];
}
-(iSQLResult *)getSingleSQLR:(iSQLResult *)SQLSource usingRow:(int)y
{
iSQLResult *SQLRAux = [[[iSQLResult alloc]init]retain];
[SQLRAux setCountX:SQLSource.CountX];
[SQLRAux addRecord:[SQLSource getRecord:y]];
[SQLRAux setFieldsNames:SQLSource.FieldsNames];
return SQLRAux;
}
-(void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{
NSLog(#"Error on XML Parse: %#", [parseError localizedDescription] );
}
//#pragma XML Parser Delegate Methods
-(void) parser:(NSXMLParser *) parser didStartElement:(NSString *) elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *) qName attributes:(NSDictionary *) attributeDict
{
if (!chunksString)
{
chunksString = [[NSString alloc] init];
}
chunksString = #"";
if ([elementName isEqualToString:#"ErrCode"])
{
loadErrNumNow = YES;
}
if ([elementName isEqualToString:#"ErrDesc"])
{
loadErrDesNow = YES;
}
if ([elementName isEqualToString:#"Table"])
{
Found = YES;
loadFieldsNow = NO;
tempRecord = [[NSMutableArray alloc] init];
}
if (Found && ![elementName isEqualToString:#"Table"])
{
loadFieldsNow = YES;
if (!FieldsReaded)
{
[SQLR addField:elementName];
}
}
}
-(void) parser:(NSXMLParser *) parser foundCharacters:(NSString *)string
{
chunksString = [chunksString stringByAppendingString:string];
}
-(void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
NSString * finalString;
finalString = [NSString stringWithFormat:#"%#",chunksString];
if (loadErrNumNow)
{
[SQLR setErrorCode:[finalString intValue] ];
loadErrNumNow = NO;
}
if (loadErrDesNow)
{
[SQLR setErrorDescription:finalString];
loadErrDesNow = NO;
}
if (Found)
{
if (loadFieldsNow)
{
[tempRecord addObject:finalString];
}
}
if ([elementName isEqualToString:#"Table"])
{
[SQLR addRecord:tempRecord];
[tempRecord release];
Found = NO;
FieldsReaded = YES;
loadFieldsNow = NO;
}
}
-(void)dealloc
{
if (SQLR)
{
[SQLR release];
SQLR = nil;
}
[URLConnection release];
[super dealloc];
}
#end
This is an absolutely buggy class because the leaks, every access is a leak :(
Any help please?

Here are some things I notice:
-[iSQLResult copyWithZone:]
You're sending the result of mutableCopyWithZone: (which returns a retained object) to the setters, which retain the object again. One way to fix it is to autorelease the copy:
[SQLRCopy setRecords:[[self.Records mutableCopyWithZone:zone] autorelease]]
-[iSQL SQLExec:] and -[iSQL SQLReader:]
The ivars WSC and xmlPareser are alloced then released but not set to nil. This isn't a leak, but you're keeping a reference to a released object. If you dereference that, you'll crash.
-[iSQL getSingleSQLR:usingRow:]
iSQLResult *SQLRAux = [[[iSQLResult alloc]init]retain];
Did you mean autorelease instead of retain there? (And if you did, shouldn't you also autorelease the return in getSQLR, for consistency?)
-[iSQL parser:didStartElement:namespaceURI:qualifiedName:attributes:]
chunksString is alloced (+1 retain), but later in parser:foundCharacters: you're losing the reference (i.e., leaking the string) and replacing it with an autoreleased string.
That's all I notice off hand. It sounds like you're leaking more than just those objects, so I'm guessing you're leaking iSQL and/or iSQLResult objects, too. Remember, when you leak an object, you also leak everything those objects hold a reference to. Even if these classes were leak-free, if the code that's instantiating the classes isn't properly releasing the objects you'll see all the members in these classes leak, too. When fixing leaks, always look for "top-level" objects first.

Related

XML Parsing goes to EXC_BAD_ACCESS code 1 address 0x10

So here is the thing. I am trying to build no-ARC/no-Storyboard project without previous experience in manual memory-management.
Full source code available here.
So what I've got here is a
class, which helps me create Products object with custom initialiser
Products.h
#interface Products : NSObject
#property (nonatomic,retain)NSString *productName;
#property (nonatomic,retain)NSString *productDescription;
#property (nonatomic,retain)NSString *productImage;
-(id) initWithName: (NSString *) name
description: (NSString *) description
image: (NSString *) image;
#end
Products.m
#implementation Products
-(id) initWithName:(NSString *)name description:(NSString *)description image:(NSString *)image {
self = [super init];
if (self) {
self.productName = name;
self.productDescription = description;
self.productImage = image;
}
return self;
#end
There you can see ProductParser class, which one contains most of magic
ProductsParser.h
#interface ProductsParser : NSObject <NSXMLParserDelegate>
#property (nonatomic,retain) NSMutableArray *productArray;
-(id) initWithArray:(NSMutableArray *) productArray;
-(void) parseXMLFile;
#end
ProductParser.m
// Creating private properties
#interface ProductsParser()
#property NSXMLParser *parser;
#property NSString *element;
#property NSMutableString *currentProductName;
#property NSMutableString *currentProductDescription;
#property NSMutableString *currentProductImage;
#end
#implementation ProductsParser
-(id) initWithArray:(NSMutableArray *)productArray {
self = [super init];
if (self) {
self.productArray = productArray;
}
return self;
}
-(void) parseXMLFile {
// We will do it here instead of writing that in viewDidLoad
NSURL *xmlPath = [[NSBundle mainBundle]URLForResource:#"productsList" withExtension:#"xml" ];
self.parser = [[NSXMLParser alloc]initWithContentsOfURL:xmlPath];
self.parser.delegate = self;
[self.parser parse];
[self.parser release];
}
-(void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
self.element = elementName;
}
-(void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
string = [string stringByReplacingOccurrencesOfString:#"\n" withString:#""];
string = [string stringByReplacingOccurrencesOfString:#"\t" withString:#""];
string = [string stringByReplacingOccurrencesOfString:#" " withString:#""];
if ([self.element isEqualToString:#"Name"]) {
if (self.currentProductName == nil) {
self.currentProductName = [[NSMutableString alloc] initWithString:string];
} else {
[self.currentProductName appendString:string];
}
}
if ([self.element isEqualToString:#"Description"]) {
if (self.currentProductDescription == nil) {
self.currentProductDescription = [[NSMutableString alloc] initWithString:string];
} else {
[self.currentProductDescription appendString:string];
}
} if ([self.element isEqualToString:#"Image"]) {
if (self.currentProductImage == nil) {
self.currentProductImage = [[NSMutableString alloc] initWithString:string];
} else {
[self.currentProductImage appendString:string];
}
}
}
-(void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:#"Product"]) {
Products *thisProduct = [[Products alloc] initWithName:self.currentProductName description:self.currentProductDescription image:self.currentProductImage];
[self.productArray addObject:thisProduct];
[self.currentProductName release];
self.currentProductName = nil;
[self.currentProductDescription release];
self.currentProductDescription = nil;
[self.currentProductImage release];
self.currentProductImage = nil;
[thisProduct release];
thisProduct = nil;
[self.element release];
self.element = nil;
}
}
#end
Later on, in the class which is suppose to handle the UITableView I am creating:
#property (retain,nonatomic)NSMutableArray *productArray;
And In viewDidLoad we have this code
self.productArray = [[NSMutableArray alloc] init];
ProductsParser *menuParser = [[ProductsParser alloc] initWithArray:self.productArray];
[menuParser parseXMLFile];
[menuParser release];
All that results in EXC_BAD_ACCESS pointing to
#property (nonatomic,retain)NSString *productName;
I've done some research about that error. Users claims that they successfully getting rid of that error by simply calling properties with self. syntax.(which is suppose to increase retain count?) In my case it is not the issue, as you may see.(Or did I missed something?)
I am also can see in debugger that productArray which is suppose to be populated with my products from .xml file, is in fact populated by trash stuff like #"/n/t" #"/n " #"/n/t" and so on.(why why why?!)
So at least point it to me, where to start. Really appreciate your guys help.
UPDATE 1: Apparently there was some defect logic, I almost got rid of the \n\t stuff by changing code in foundCharacters section.
So now instead of just \n\t \n \n\t I got actual data in my array with those afterwards. Like so:
#"Box of chocolate \n\t\t"
#"Box of chocolate, very tasty \n"
#"ImageName \n\t"
I know that \n should be like new line, and \t is apparently tabulation. Still, don't have a clear idea on how to completely get rid of those and why are they popping up.
UPDATE 2: I manage to get rid of the trashy \n\t from the array by adding stringByReplacingOccurrencesOfString. (code updated)

No visible #interface for 'BinaryFileReader' declares the selector 'initWithLocation:'

I am having an this error come up:
No visible #interface for 'BinaryFileReader' declares the selector 'initWithLocation:'
for every method called on BinaryFileReader in the method below.
+ (Item*)loadItem:(NSString*)filepath {
Item* newItem = [[Item alloc] init];
BinaryFileReader* input = [[BinaryFileReader alloc] initWithLocation:filepath];
[newItem setName:[input readNSString]];
[newItem setOtherNames:[input readNSMutableArrayOfNSString]];
[newItem setDescription:[input readNSString]];
[newItem setXactCode:[input readNSString]];
[newItem setSymbilityCode:[input readNSString]];
[newItem setAverageLowPrice:[input readInt]];
[newItem setAverageHighPrice:[input readInt]];
[newItem setAverageLifeExpectancy:[input readInt]];
return newItem;
}
Here is my BinaryFileReader.m:
#import "BinaryFileReader.h"
#implementation BinaryFileReader
- (id)init {
self = [super init];
return self;
}
- (id)initWithLocation:(NSString*)filepath {
if ((self = [super init])) {
_file = [NSFileHandle fileHandleForReadingAtPath:filepath];
_fileOffset = 0;
if (_file == nil)
NSLog(#"%#%#",#"Failed to open file at path:",filepath);
}
return self;
}
- (void)close {
[_file closeFile];
}
- (int)readInt {
[_file seekToFileOffset:_fileOffset];
_databuffer = [_file readDataOfLength:4];
_fileOffset+=4;
return (*(int*)([_databuffer bytes]));
}
- (NSString*)readNSString {
int length = [self readInt];
[_file seekToFileOffset:_fileOffset];
_databuffer = [_file readDataOfLength:length];
_fileOffset+=length;
return [[NSString alloc] initWithData:_databuffer encoding:NSUTF8StringEncoding];
}
- (NSMutableArray*)readNSMutableArrayOfNSString {
NSMutableArray* array = [[NSMutableArray alloc] init];
int arrayLength = [self readInt];
int length;
for (int i=0; i<arrayLength; i++) {
length = [self readInt];
[_file seekToFileOffset:_fileOffset];
_databuffer = [_file readDataOfLength:length];
_fileOffset+=length;
[array addObject:[[NSString alloc] initWithData:_databuffer encoding:NSUTF8StringEncoding]];
}
return array;
}
#end
And BinaryFileReader.h:
#interface BinaryFileReader : NSObject
#property (nonatomic) int fileOffset;
#property (nonatomic, retain) NSData* databuffer;
#property (nonatomic, retain) NSFileHandle* file;
- (id)init;
- (id)initWithLocation:(NSString*)filepath;
- (void)close;
- (int)readInt;
- (NSString*)readNSString;
- (NSMutableArray*)readNSMutableArrayOfNSString;
#end
I don't understand why I am having this issue. Any help to clear this up would be much appreciated.
I copy&pasted the code from your question into a project of mine. Expected result: Everything compiles fine. So it's definitely not your code that is the problem.
Coming back to the idea of a different BinaryFileReader.h polluting your #imports: Do you use any third party libraries in your project? If yes, one of those might unexpectedly provide a BinaryFileReader.h file.
Try this: Rename BinaryFileReader.h to something else, e.g. Foo.h. Also change the #import in BinaryFileReader.m to use Foo.h, but leave the #import in the file where your loadItem: method is located so that it still uses BinaryFileReader.h. Now compile again. The compiler should now complain that it can't find BinaryFileReader.h. If the error is still about the missing selector then you know that somewhere you have an unexpected BinaryFileReader.h messing up your project.

Try to load a created Map in MKMapView

I am trying to load my Map which I created with a kml File in Google-Maps. The Google Maps Link. I have to say it is only an example, but it is the same principle.
The easiest way is to load in a WebView, but that is ugly in my eyes.
Thank you for reading my Question!
Best regards CTS
To load a KML into a MKMapView:
Add the necessary frameworks (MapKit.framework and CoreLocation.framework) to your target;
Load and parse the KML;
Create your annotations on the basis of the KML; and
Set your map's region to encompass the annotations.
Thus, that might look like:
#import <MapKit/MapKit.h>
- (void)loadKml:(NSURL *)url
{
// parse the kml
Parser *parser = [[Parser alloc] initWithContentsOfURL:url];
parser.rowElementName = #"Placemark";
parser.elementNames = #[#"name", #"Snippet", #"coordinates", #"description"];
parser.attributeNames = nil;
[parser parse];
// add annotations for each of the entries
for (NSDictionary *locationDetails in parser.items)
{
MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
annotation.title = locationDetails[#"name"];
annotation.subtitle = locationDetails[#"Snippet"];
NSArray *coordinates = [locationDetails[#"coordinates"] componentsSeparatedByString:#","];
annotation.coordinate = CLLocationCoordinate2DMake([coordinates[1] floatValue], [coordinates[0] floatValue]);
[self.mapView addAnnotation:annotation];
}
// update the map to focus on the region that encompasses all of your annotations
MKCoordinateRegion region;
if ([self.mapView.annotations count] > 1)
{
region = [self regionForAnnotations:self.mapView.annotations];
region = MKCoordinateRegionMake(region.center, MKCoordinateSpanMake(region.span.latitudeDelta * 1.05, region.span.longitudeDelta * 1.05)); // expand the region by 5%
}
else
{
id<MKAnnotation> annotation = self.mapView.annotations[0];
region = MKCoordinateRegionMakeWithDistance(annotation.coordinate, 100.0, 100.0);
}
[self.mapView setRegion:region animated:YES];
}
My Parser class is just a NSXMLParser subclass that I've written that will create an array of items one per occurrence of rowElementName, and for each row, it will grab the elements listed in the elementNames array.
Parser.h:
#import <Foundation/Foundation.h>
#interface Parser : NSXMLParser
#property (nonatomic, strong) NSString *rowElementName; // this is the element name that identifies a new row of data in the XML
#property (nonatomic, strong) NSArray *attributeNames; // this is the array of attributes we might want to retrieve for that element name
#property (nonatomic, strong) NSArray *elementNames; // this is the list of sub element names for which we're retrieving values
#property (nonatomic, strong) NSMutableArray *items; // after parsing, this is the array of parsed items
#end
Parser.m:
#import "Parser.h"
#interface Parser () <NSXMLParserDelegate>
#property (nonatomic, strong) NSMutableDictionary *item; // while parsing, this is the item currently being parsed
#property (nonatomic, strong) NSMutableString *elementValue; // this is the element within that item being parsed
#end
#implementation Parser
- (id)initWithContentsOfURL:(NSURL *)url
{
self = [super initWithContentsOfURL:url];
if (self)
{
self.delegate = self;
}
return self;
}
- (id)initWithData:(NSData *)data
{
self = [super initWithData:data];
if (self)
{
self.delegate = self;
}
return self;
}
- (id)initWithStream:(NSInputStream *)stream
{
self = [super initWithStream:stream];
if (self)
{
self.delegate = self;
}
return self;
}
#pragma mark - NSXMLParserDelegate methods
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
self.items = [[NSMutableArray alloc] init];
if (!self.rowElementName)
NSLog(#"%s Warning: Failed to specify row identifier element name", __FUNCTION__);
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:self.rowElementName])
{
self.item = [[NSMutableDictionary alloc] init];
for (NSString *attributeName in self.attributeNames)
{
id attributeValue = [attributeDict valueForKey:attributeName];
if (attributeValue)
[self.item setObject:attributeValue forKey:attributeName];
}
}
else if ([self.elementNames containsObject:elementName])
{
self.elementValue = [[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (self.elementValue)
{
[self.elementValue appendString:string];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:self.rowElementName])
{
[self.items addObject:self.item];
self.item = nil;
}
else if ([self.elementNames containsObject:elementName])
{
[self.item setValue:self.elementValue forKey:elementName];
self.elementValue = nil;
}
}
#end
Finally, the only other utility method that my loadKml uses is regionForAnnotations, which defines a region based upon a series of annotations. Rob Mooney wrote a simple routine to do that:
- (MKCoordinateRegion)regionForAnnotations:(NSArray *)annotations {
CLLocationDegrees minLat = 90.0;
CLLocationDegrees maxLat = -90.0;
CLLocationDegrees minLon = 180.0;
CLLocationDegrees maxLon = -180.0;
for (id <MKAnnotation> annotation in annotations) {
if (annotation.coordinate.latitude < minLat) {
minLat = annotation.coordinate.latitude;
}
if (annotation.coordinate.longitude < minLon) {
minLon = annotation.coordinate.longitude;
}
if (annotation.coordinate.latitude > maxLat) {
maxLat = annotation.coordinate.latitude;
}
if (annotation.coordinate.longitude > maxLon) {
maxLon = annotation.coordinate.longitude;
}
}
MKCoordinateSpan span = MKCoordinateSpanMake(maxLat - minLat, maxLon - minLon);
CLLocationCoordinate2D center = CLLocationCoordinate2DMake((maxLat - span.latitudeDelta / 2), maxLon - span.longitudeDelta / 2);
return MKCoordinateRegionMake(center, span);
}

Which one is the right method of initializing a NSMutableDictionary . Please anyone correct me here

I am trying to create a NSMutableDictionary in my class. I have read many post in stackoverflow to understand the difference. But now i am totally confused. So any one correct me , which one is the correct way of initialing a NSMutableDictionary in my class . I have to access this dictiionary in many areas of my application .So suggest me the good way of using the variable initialization ...
/// .h file
#interface ActiveFeeds : NSObject {
}
#property (nonatomic, copy) NSMutableDictionary *invDictionary;
#property (nonatomic, retain) NSString *filePath;
#end
#implementation ActiveFeeds
#synthesize filePath;
#synthesize invDictionary;
- (id)init{
self = [super init];
if (self != nil){
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:self.filePath];
self.invDictionary = [dictionary mutableCopy];
dictionary release];
}
return self;
}
/* And use self.invDictionary all in the application */
- (void)setObjectAtKey:(NSMutableDictionary *)objectDic atKey:(NSString *)setKey{
[self.invDictionary setObject:objectDic forKey:setKey];
}
- (void)dealloc {
[self.invDictionary release];
[self.filePath release];
[super dealloc];
}
#end
or like this ....
#interface ActiveFeeds : NSObject {
NSMutableDictionary *invDictionary;
NSString *filePath;
}
#end
#implementation ActiveFeeds
- (id)init{
self = [super init];
if (self != nil){
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
invDictionary = [dictionary mutableCopy];
[dictionary release];
}
}
return self;
}
/* And use invDictionary all in the application */
- (void)setObjectAtKey:(NSMutableDictionary *)objectDic atKey:(NSString *)setKey{
[invDictionary setObject:objectDic forKey:setKey];
}
- (void)dealloc {
[invDictionary release];
[filePath release];
[super dealloc];
}
#end
Please any one help me to get the correct way of using the variables ....
- (id)initWithFilePath:(NSString *)path{
self = [super init];
if (self != nil){
self.filePath = path;
self.invDictionary = [NSMutableDictionary dictionaryWithContentsOfFile:path];
}
return self;
}
also
- (void)dealloc {
[invDictionary release];
[filePath release];
[super dealloc];
}

objects in nsmutablearray becoming zombies

i am developing very simple quiz app
In viewDidLoad i am adding objects in myarray
where ever i nslog myarray values it works fine
but if i try this inside ibaction methods all objects becomes zombie
for 2 days i am stuck in this but can't find it what is wrong.
quiz.h
#import <UIKit/UIKit.h>
#import <sqlite3.h>
#class dbVals;
#class viewTransition;
#class AppDelegate;
#interface quiz : UIViewController
{
NSMutableArray *myarray;
IBOutlet UITextView *questionTextView_;
IBOutlet UIButton *skipButton_;
IBOutlet UIButton *optionAButton_;
IBOutlet UIButton *optionBButton_;
IBOutlet UIButton *optionCButton_;
NSString *correctAnswer;
int questionNumber;
int score;
IBOutlet UILabel *scoreLabel_;
int totalQuestions;
}
-(void)populate:(int)number;
//#property(nonatomic, retain) NSMutableArray *myarray;
#property (retain, nonatomic) IBOutlet UITextView *questionTextView;
#property (retain, nonatomic) IBOutlet UIButton *skipButton;
#property (retain, nonatomic) IBOutlet UIButton *optionAButton;
#property (retain, nonatomic) IBOutlet UIButton *optionBButton;
#property (retain, nonatomic) IBOutlet UIButton *optionCButton;
#property (retain, nonatomic) IBOutlet UILabel *scoreLabel;
- (IBAction)optionsToAnswer:(id)sender;
- (IBAction)zzz:(id)sender;
#end
quiz.m
#import "quiz.h"
#import "DbVals.h"
#import "viewTransition.h"
#import "AppDelegate.h"
#implementation quiz
#synthesize skipButton=skipButton_;
#synthesize optionAButton=optionAButton_;
#synthesize optionBButton=optionBButton_;
#synthesize optionCButton=optionCButton_;
#synthesize scoreLabel=scoreLabel_;
#synthesize questionTextView=questionTextView_;
//#synthesize myarray;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)createEditableCopyOfDatabaseIfNeeded
{
//NSLog(#"Creating editable copy of database");
// First, test for existence.
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"oq.sqlite"];
success = [fileManager fileExistsAtPath:writableDBPath];
if (success) return;
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"oq.sqlite"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!success) {
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
}
+(sqlite3 *) getNewDBConnection
{
sqlite3 *newDBconnection;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"oq.sqlite"];
// Open the database. The database was prepared outside the application.
if (sqlite3_open([path UTF8String], &newDBconnection) == SQLITE_OK) {
//NSLog(#"Database Successfully Opened ");
} else {
NSLog(#"Error in opening database ");
}
return newDBconnection;
}
- (void)viewDidLoad
{
[super viewDidLoad];
questionNumber = 0;
score = 0;
[self createEditableCopyOfDatabaseIfNeeded];
sqlite3 *dbc = [quiz getNewDBConnection];
sqlite3_stmt *statement = nil;
const char *sqlSelect = "select * from QnA ORDER BY RANDOM()";
if(sqlite3_prepare_v2(dbc, sqlSelect, -1, &statement, NULL)!=SQLITE_OK)
{
NSAssert1(0, #"Error Preparing Statement", sqlite3_errmsg(dbc));
}
else
{
myarray = [[NSMutableArray alloc]init];
while(sqlite3_step(statement)==SQLITE_ROW)
{
NSString *q = [NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 0)];
NSString *o = [NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 1)];
NSString *a = [NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 2)];
DbVals *dbValsObj = [[DbVals alloc]init];
[dbValsObj setValsOfQuestions:q options:o answer:a];
[myarray addObject:dbValsObj];
[dbValsObj release];
}
}
sqlite3_finalize(statement);
//[self populate:questionNumber];
}
-(void)populate:(int)number
{
/*[scoreLabel_ setText:[NSString stringWithFormat:#"%d",score]];
AppDelegate *appDel = [[UIApplication sharedApplication] delegate];
[appDel setFinalScore:[NSString stringWithFormat:#"%d",score]];
if(number < [myarray count])
{
DbVals *dbv1 = [myarray objectAtIndex:number];
[questionTextView_ setText:[dbv1 getQuestions]];
NSString *joinedOptions = [dbv1 getOptions];
NSArray *splitOptions = [joinedOptions componentsSeparatedByString:#","];
[optionAButton_ setTitle:[splitOptions objectAtIndex:0] forState:UIControlStateNormal];
[optionBButton_ setTitle:[splitOptions objectAtIndex:1] forState:UIControlStateNormal];
[optionCButton_ setTitle:[splitOptions objectAtIndex:2] forState:UIControlStateNormal];
correctAnswer = [dbv1 getAnswer];
}
else
{
//viewTransition *vt = [[viewTransition alloc]init];
[viewTransition viewsTransitionCurrentView:self toNextView:#"result"];
//[vt release];
}*/
}
- (void)viewDidUnload
{
for(int i=0; i<[myarray count]; i++)
{
DbVals *dbv1 = [myarray objectAtIndex:i];
NSLog(#"%#",[dbv1 getQuestions]);
NSLog(#"%#",[dbv1 getOptions]);
NSLog(#"%#",[dbv1 getAnswer]);
NSLog(#"<u><u><u><u><><><><><><><><><><><>");
}
[self setQuestionTextView:nil];
[questionTextView_ release];
questionTextView_ = nil;
[self setQuestionTextView:nil];
[skipButton_ release];
skipButton_ = nil;
[self setSkipButton:nil];
[optionAButton_ release];
optionAButton_ = nil;
[self setOptionAButton:nil];
[optionBButton_ release];
optionBButton_ = nil;
[self setOptionBButton:nil];
[optionCButton_ release];
optionCButton_ = nil;
[self setOptionCButton:nil];
[scoreLabel_ release];
scoreLabel_ = nil;
[self setScoreLabel:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc
{
for(int i=0; i<[myarray count]; i++)
{
DbVals *dbv1 = [myarray objectAtIndex:i];
NSLog(#"%#",[dbv1 getQuestions]);
NSLog(#"%#",[dbv1 getOptions]);
NSLog(#"%#",[dbv1 getAnswer]);
NSLog(#"<d><d><d><d><d><><><><><><><><><><>");
}
[questionTextView_ release];
[skipButton_ release];
[optionAButton_ release];
[optionBButton_ release];
[optionCButton_ release];
[scoreLabel_ release];
[myarray release];
[super dealloc];
}
- (IBAction)optionsToAnswer:(id)sender
{
for(int i=0; i<[myarray count]; i++)
{
DbVals *dbv1 = [myarray objectAtIndex:i];
NSLog(#"%#",[dbv1 getQuestions]);
NSLog(#"%#",[dbv1 getOptions]);
NSLog(#"%#",[dbv1 getAnswer]);
NSLog(#"six");
}
if(sender == skipButton_)
{
//questionNumber++;
//[self populate:questionNumber];
/*[UIView animateWithDuration:5 delay:0 options: UIViewAnimationCurveEaseOut
animations:
^{
[UIView setAnimationTransition:103 forView:self.view cache:NO];
}
completion:
^(BOOL finished)
{
}
];*/
}
if(sender == optionAButton_)
{
/*NSString *one = #"1";
if([correctAnswer isEqualToString:one])
{
score++;
}
questionNumber++;
[self populate:questionNumber];*/
}
if(sender == optionBButton_)
{
/*NSString *two = #"2";
if([correctAnswer isEqualToString:two])
{
score++;
}
questionNumber++;
[self populate:questionNumber];*/
}
if(sender == optionCButton_)
{
/*NSString *three = #"3";
if([correctAnswer isEqualToString:three])
{
score++;
}
questionNumber++;
[self populate:questionNumber];*/
}
}
- (IBAction)zzz:(id)sender
{
}
#end
dbVals.h
#import <Foundation/Foundation.h>
#interface DbVals : NSObject
{
NSString *questions_;
NSString *options_;
NSString *answer_;
// NSString *hint;
// NSString *mode;
}
-(void)setValsOfQuestions:(NSString*)questions options:(NSString*)options answer:(NSString*)answer;
-(NSString*)getQuestions;
-(NSString*)getOptions;
-(NSString*)getAnswer;
dbVals.m
#import "DbVals.h"
#implementation DbVals
-(void)setValsOfQuestions:(NSString*)questions options:(NSString*)options answer:(NSString*)answer
{
questions_ = questions;
options_ = options;
answer_ = answer;
}
-(NSString*)getQuestions
{
return questions_;
}
-(NSString*)getOptions
{
return options_;
}
-(NSString*)getAnswer
{
return answer_;
}
#end
Your dbVals.m setVals isn't retaining the parameters. This obviously means, everything inside becomes deallocated once the function scope ends.
Try changing it to something like
-(void)setValsOfQuestions:(NSString*)questions options:(NSString*)options answer:(NSString*)answer
{
[questions_ release];
[options_ release];
[answer_ release];
questions_ = [questions copy];
options_ = [options copy];
answer_ = [answer copy];
}

Resources