I'm working with a database, and trying to store the rows of a table as dictionary in an Array.
#import "RootViewController.h"
#import "ProgettoAppDelegate.h"
#import "AddItemViewController.h"
#import "DetailViewController.h"
#include <sqlite3.h>
#implementation RootViewController
#synthesize nibLoadedCell;
#synthesize addItem;
NSNumberFormatter *priceFormatter;
NSDateFormatter *dateFormatter;
NSMutableArray *shoppingListItems; <--i created here...
NSDictionary *editItem;
-(void) loadDataFromDb {
//apriamo il database
sqlite3 *db;
int dbrc; //Codice di ritorno del database (database return code)
ProgettoAppDelegate *appDelegate = (ProgettoAppDelegate *) [UIApplication sharedApplication].delegate;
const char *dbFilePathUTF8 = [appDelegate.dbFilePath UTF8String];
dbrc = sqlite3_open(dbFilePathUTF8, &db);
if (dbrc) {
NSLog(#"Impossibile aprire il Database!");
return;
}
//database aperto! Prendiamo i valori dal database.
sqlite3_stmt *dbps; //Istruzione di preparazione del database
NSString *queryStatementNS = #"select key, item, price, groupid, dateadded from shoppinglist order by item";
const char *queryStatement = [queryStatementNS UTF8String];
dbrc = sqlite3_prepare_v2(db, queryStatement, -1, &dbps, NULL);
//Richiamo la funzione sqlite3_step() finché ho righe nel database
while ((dbrc = sqlite3_step(dbps)) == SQLITE_ROW) {
int primaryKeyValueI = sqlite3_column_int(dbps, 0);
NSNumber *primaryKeyValue = [[NSNumber alloc] initWithInt:primaryKeyValueI];
NSString *itemValue = [[NSString alloc] initWithUTF8String:(char*) sqlite3_column_text(dbps, 1)];
double priceValueD = sqlite3_column_double(dbps, 2);
NSNumber *priceValue = [[NSNumber alloc] initWithDouble:priceValueD];
int groupValueI = sqlite3_column_int(dbps, 3);
NSNumber *groupValue = [[NSNumber alloc] initWithInt:groupValueI];
NSString *dateValueS = [[NSString alloc] initWithUTF8String:(char*) sqlite3_column_text(dbps, 4)];
NSDate *dateValue = [dateFormatter dateFromString: dateValueS];
NSMutableDictionary *rowDict = [[NSMutableDictionary alloc] initWithCapacity:5];
[rowDict setObject:primaryKeyValue forKey: ID_KEY];
[rowDict setObject:itemValue forKey: ITEM_KEY];
[rowDict setObject:priceValue forKey: PRICE_KEY];
[rowDict setObject:groupValue forKey: GROUP_ID_KEY];
[rowDict setObject:dateValue forKey: DATE_ADDED_KEY];
[shoppingListItems addObject: rowDict];
NSLog(#"%d", [shoppingListItems count]); //I have a Breakpoint here!
//rilascio tutti gli elementi
[dateValue release];
[primaryKeyValue release];
[itemValue release];
[priceValue release];
[groupValue release];
[rowDict release];
}
}
using Breakpoint at the end of the procedure, i can see that in the variables there are the contents of the database, but array "shoppingListItems" is empty. (count = 0)
If you are brave enough to take a look, here there is the entire project: http://cl.ly/9uvb
You need to declare all your variables as instance variables, i mean in the .h file as shown below
// .h
#interface RootViewController : UITableViewController {
UITableViewCell *nibLoadedCell;
AddItemViewController *addItem;
IBOutlet UITableView *tableView;
NSNumberFormatter *priceFormatter;
NSDateFormatter *dateFormatter;
NSMutableArray *shoppingListItems; // <--- this is only a declaration (not creates the object)
NSDictionary *editItem;
}
And correctly initialize the objects, viewDidLoad is a good place to do this work:
//.m
- (void)viewDidLoad
{
[super viewDidLoad];
shoppingListItems = [NSMutableArray new]; // <---- This create the object
// other initialization ....
if (!dateFormatter) {
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeZone: [NSTimeZone timeZoneWithAbbreviation:#"UTC"]];
[dateFormatter setDateFormat:#"yyy-MM-dd HH:mm:ss"];
}
if (! priceFormatter) {
priceFormatter = [[NSNumberFormatter alloc] init];
[priceFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
}
self.navigationItem.leftBarButtonItem = self.editButtonItem;
}
Your problem resides on a nil value for shoppingListItems also dont forget to release the variable on your dealloc method
You have not shown the definition of shoppingListItems but there are two common problems when adding to an array:
The array is an NSArray and not a NSMutableArray as it must be
The array is nil - you may have created it using [NSMutableArray array] without explicit retain?
Yeah, checked your code - you never initialise it at all. Fix that and you should be OK.
I don't see anything in your code above that creates the array. If shoppingListItems is nil, then those -addObject: messages do nothing.
It sounds like you aren't ever actually creating the array to go in shoppingListItems, so it's nil.
Related
SO here's my setup. I have an object called radiostations where I have several strings like callsign, frequency declared and an NSMutableArray called amStationInfo. On my viewcontroller, I access an SQLite database which populates the an array like so...
radiostations.h
#interface radiostations : NSObject {
NSString *format;
NSString *city;
}
#property (nonatomic, retain) NSString *format;
#property (nonatomic, retain) NSString *city;
ViewController.m
radiostations *amStationClass = [[radiostations alloc] init];
NSMutableArray* amStationInfo = [[NSMutableArray alloc] init];
while (sqlite3_step(statement) == SQLITE_ROW)
{
NSString *cityField = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 10)];
NSString *formatField = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 0)];
[amStationInfo addObject:amStationClass];
[amStationClass setCity:cityField];
[amStationClass setFormat:formatField];
}
[tabView reloadData];
sqlite3_finalize(statement);
and then I populate a UITableView
NSString *cityValue = [(radiostations *)[amStationInfo objectAtIndex:indexPath.row] city];
NSString *formatValue = [(radiostations *)[amStationInfo objectAtIndex:indexPath.row] format];
cityLabel.text = cityValue;
formatLabel.text = formatValue;
Initially I was dealing with a few Arrays and this worked just fine. I then changed it so that I was only dealing with one array using a class object and now it's not working. I know the SQLite query and what not works so Im not having any problems with that. It seems as though the array does not get populated.
You are changing the properties of the same radiostations object and adding it over and over again to the array. You need to create a new radiostations object for each row from your sqlite database and add this:
while (...) {
// fetch data as before
radiostations *record = [[radiostations alloc] init];
[record setCity: cityField];
[record setFormat: formatField];
[amStationInfo addObject: record];
[record release];
}
If you are using ARC you need to remove the line [record release];, otherwise it is necessary to avoid leaking those objects.
where did you allocate/init your mutablearray?
something like:
NSMutableArray* amStationInfo = [[NSMutableArray alloc] init];
you need to allocate it once, before to add objects in it
Hi, I am trying to get array from StudentDbwithsearchbarViewController class to SearchBarDB class but resultant array not having any data it is giving null Array. Please help me out with this.
thanks in advance
#import <UIKit/UIKit.h>
#interface StudentDbwithsearchbarViewController : UIViewController<UITableViewDelegate,UITableViewDataSource> {
IBOutlet UITextField *txtMarks,*txtSname;
IBOutlet UITableView *tableStudents;
NSMutableArray *arrStudents;
}
#property(nonatomic,retain) NSMutableArray *arrStudents;
-(IBAction)saveStudentDetails;
-(IBAction)gotoSearchpage;
#end
#implementation StudentDbwithsearchbarViewController
#synthesize arrStudents;
- (void)viewDidLoad {
[super viewDidLoad];
arrStudents = [[DbStudent getStudentRecords]retain];
NSLog(#"%#",arrStudents);
NSLog(#"%d",[arrStudents retainCount]);
}
#import "DbStudent.h"
+(NSMutableArray*)getStudentRecords{
NSArray *arrDocPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *strDestPath = [NSString stringWithFormat:#"%#/Student5.sqlite",[arrDocPath objectAtIndex:0]];
NSMutableArray *arrStudents = [[NSMutableArray alloc]init];
sqlite3 *db;
if(sqlite3_open([strDestPath UTF8String], &db)==SQLITE_OK)
{
NSString *query = #"SELECT * FROM Student";
void* v;
char* err_msg;
sqlite3_stmt *studentStmt;
if(sqlite3_prepare_v2(db, [query UTF8String], -1, &studentStmt, &err_msg)==SQLITE_OK)
{
while (sqlite3_step(studentStmt)==SQLITE_ROW) {
int sno = sqlite3_column_int(studentStmt, 0);
NSString *sname = [NSString stringWithUTF8String: sqlite3_column_text(studentStmt, 1)];
float marks = sqlite3_column_double(studentStmt, 2);
Student *st = [[Student alloc]init];
st.Sno = sno;
st.Sname = sname;
st.marks = marks;
[arrStudents addObject:st];
}
}
}
return arrStudents;
}
#import "SearchBarDB.h"
#import"StudentDbwithsearchbarViewController.h"
- (void)viewDidLoad {
[super viewDidLoad];
StudentDbwithsearchbarViewController *sbd = [[StudentDbwithsearchbarViewController alloc]init];
NSLog(#"%d",[sbd.arrStudents retainCount]);
NSLog(#"%#",sbd.arrStudents);
// arrstudentBase = [sbd.arrStudents copy];
arrMatchedString = [[NSMutableArray alloc]init];
}
Lots of potential problems, no definitive answer without a clue as to what you've tried or how you've determined that it failed.
methods should not be prefixed with get; just call it studentRecords or fetchStudentRecords
your memory management code is all over the place; you'll be leaking that array, at the least.
retainCount is useless, don't call it.
writing raw SQL is a waste of time; at least use a wrapper like FMDB or, better yet, move to CoreData
Best guess for failure: the database doesn't exist or the query fails. Have you stepped through the query code?
-(id) initWithData:(NSString *)lastName: (NSString *)firstName{
self->firstname = firstName;
self->lastname = lastName;
return self;
}
-(void) printData {
NSLog(#"firstname: %#", firstname);
NSLog(#"lastname: %#", lastname);
}
so whenever I create a new object using the above init function. And Add objects to a NSMutableArray, using the addObject function.
NSMutableArray *objectArray = [[NSMutableArray alloc] init];
CustomObject *tempObject = [[CustomObject alloc] initWithData: #"smith": #"john"];
CustomObject *tempObjectb = [[CustomObject alloc] initWithData: #"brown": #"william"];
[objectArray addObject:tempObject];
[objectArray addObject:tempObjectb];
[[objectArray objectAtIndex:0] printData];
[[objectArray objectAtIndex:1] printData];
objects at index 1, and 0 always equal the whichever object was added to the array last.
This also happens if I use a for loop, or have more than 2 objects, all values when printed, turn to the values of the last added object to the objectArray. Let me know if there is any information that I am missing.
Is there something that I am missing?
Fix your initWithData:lastName: implementation as following:
-(id) initWithData:(NSString *)lastName: (NSString *)firstName
{
self = [super init];
if ( nil != self ) {
self->firstname = [firstName retain];
self->lastname = [lastName retain];
}
return self;
}
I'm quite new to Xcode and I have a huge problem with a tutorial I'm working on.
I'm trying to write a simple shopping list, using a sql database.
Actually i finished with the project. I triple checked every single line of code, but for some reason it doesn't want to show me the content of the DB nor write something inside.
Really I have no idea what's wrong with the code...
Writing in the DB:
-(IBAction)addShoppingListItem:(id)sender {
//apriamo il database
if (([itemNameField.text length] == 0) || ([priceField.text length] == 0) || ([priceField.text doubleValue] == 0.0)) {
return;
}
sqlite3 *db;
int dbrc; //Codice di ritorno del database (database return code)
DatabaseShoppingListAppDelegate *appDelegate = (DatabaseShoppingListAppDelegate*) [UIApplication sharedApplication].delegate;
const char *dbFilePathUTF8 = [appDelegate.dbFilePath UTF8String];
dbrc = sqlite3_open(dbFilePathUTF8, &db);
if (dbrc) {
NSLog(#"Impossibile aprire il Database!");
return;
}
//database aperto! Inseriamo valori nel database.
sqlite3_stmt *dbps; //Istruzione di preparazione del database
NSString *insertStatementsNS = [NSString stringWithFormat: #"insert into \"shoppinglist\" (item, price, groupid, dateadded) values (\"%#\", %#, %d, DATETIME('NOW'))", name_field, price_field, [groupPicker selectedRowInComponent:0]];
const char *insertStatement = [insertStatementsNS UTF8String];
dbrc = sqlite3_prepare_v2(db, insertStatement, -1, &dbps, NULL);
dbrc = sqlite3_step(dbps);
//faccio pulizia rilasciando i database
sqlite3_finalize(dbps);
sqlite3_close(db);
// Pulisci i campi e indica successo nello status
statusLabel.text = [[NSString alloc] initWithFormat: #"Aggiunto %#", itemNameField.text];
statusLabel.hidden = NO;
itemNameField.text = #"";
priceField.text = #"";
}
Loading from the database:
-(void)loadDataFromDb {
//apriamo il database
sqlite3 *db;
int dbrc; //Codice di ritorno del database (database return code)
DatabaseShoppingListAppDelegate *appDelegate = (DatabaseShoppingListAppDelegate *) [UIApplication sharedApplication].delegate;
const char *dbFilePathUTF8 = [appDelegate.dbFilePath UTF8String];
dbrc = sqlite3_open(dbFilePathUTF8, &db);
if (dbrc) {
NSLog(#"Impossibile aprire il Database!");
return;
}
//database aperto! Prendiamo i valori dal database.
sqlite3_stmt *dbps; //Istruzione di preparazione del database
NSString *queryStatementNS = #"select key, item, price, groupid, dateadded from shoppinglist order by dateadded";
const char *queryStatement = [queryStatementNS UTF8String];
dbrc = sqlite3_prepare_v2(db, queryStatement, -1, &dbps, NULL);
//Richiamo la funzione sqlite3_step() finché ho righe nel database
while ((dbrc = sqlite3_step(dbps)) == SQLITE_ROW) {
int primaryKeyValueI = sqlite3_column_int(dbps, 0);
NSNumber *primaryKeyValue = [[NSNumber alloc] initWithInt:primaryKeyValueI];
NSString *itemValue = [[NSString alloc] initWithUTF8String:(char*) sqlite3_column_text(dbps, 1)];
double priceValueD = sqlite3_column_double(dbps, 2);
NSNumber *priceValue = [[NSNumber alloc] initWithDouble:priceValueD];
int groupValueI = sqlite3_column_int(dbps, 3);
NSNumber *groupValue = [[NSNumber alloc] initWithInt:groupValueI];
NSString *dateValueS = [[NSString alloc] initWithUTF8String:(char*) sqlite3_column_text(dbps, 4)];
NSDate *dateValue = [dateFormatter dateFromString: dateValueS];
NSMutableDictionary *rowDict = [[NSMutableDictionary alloc] initWithCapacity:5];
[rowDict setObject:primaryKeyValue forKey: ID_KEY];
[rowDict setObject:itemValue forKey: ITEM_KEY];
[rowDict setObject:priceValue forKey: PRICE_KEY];
[rowDict setObject:groupValue forKey: GROUP_ID_KEY];
[rowDict setObject:dateValue forKey: DATE_ADDED_KEY];
[shoppingListItems addObject: rowDict];
//rilascio tutti gli elementi
[dateValue release];
[primaryKeyValue release];
[itemValue release];
[priceValue release];
[groupValue release];
[rowDict release];
}
}
For the brave who wants to check all the project (there is just another class) here there is the link with all my work. http://www.mediafire.com/?qxfde723r29nhtb
Thanks in advance.
You have too many mistakes in your code. Let's briefly look at them:
1) In your application delegate you place db initialization code in applicationDidFinishLaunching method, but according to Apple's manuals:
This method is used in earlier versions of iOS to initialize the
application and prepare it to run. In iOS 3.0 and later, you should
use the application:didFinishLaunchingWithOptions: instead.
so, I just moved initializeDb method into - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
2) In ListViewController you have a method loadDataFromDb but I didn't find its usage. You never call this method. In the same controller you have viewWillAppear method that I used to initialize your shoppingListItems array that will be shown in tableView as follows:
-(void)viewWillAppear:(BOOL)animated {
shoppingListItems = [[NSMutableArray alloc] init];
[self loadDataFromDb];
[tableView reloadData];
}
tableView is a outlet to UITableView control that you place in your nib file. I added its declaration in ListViewController.h:
#interface ListViewController : UIViewController {
UITableViewCell *nibLoadedCell;
IBOutlet UITableView *tableView;
}
#property(nonatomic, retain) IBOutlet UITableViewCell *nibLoadedCell;
#end
and bind in interface builder with the actual control.
3) AddItemViewController's method addShoppingListItem didn't work because didn't pass this condition:
if (([itemNameField.text length] == 0) || ([priceField.text length] == 0) || ([priceField.text doubleValue] == 0.0)) {
return;
}
You didn't bind your outlets in interface builder for itemNameField, priceField, groupPicker.
By fixing this I got working solution, but actually I didn't check memory usage and suppose you have also some problem in memory management here.
Here are two methods that return a dictionary of my custom four-propery objects. They make arrays of strings, floats and BOOLs to put in the Chemical objects, then build a dictionary from the arrays. I'm new enough to the whole memory management game that I'm not always sure when I own something and when to release it. I'm making all kinds of strings on the fly.
Here's the thing: The static analyzer sees no problem with the first method, - (id)generateChlorineDictionary but says there's a leak in the second one, - (id)generateCYADictionary. It says it starts at the NSMutableArray *cyaGranulesArray... and then goes to NSDictionary *cyaDictionary... and finally to the return cyaDictionary statement.
Here are the two methods; sorry they're so long!
EDIT: Changed name from generateChlorineDictionary to newChlorineDictionary
Removed a release that happened after the return
- (id)newChlorineDictionary {
// Sets up the array for the Bleach key
NSMutableArray *bleachArray = [[NSMutableArray alloc] init];
NSArray *bleachConcentrationArray = [[NSArray alloc] initWithObjects:#"6%", #"10%", #"12%", nil];
float bleachConstantArray[] = {0.0021400, 0.0012840, 0.0010700};
for (int i=0; i<3; i++) {
Chemical *bleachChemical = [[Chemical alloc] initWithChemical:#"Bleach"
andConcentration:[bleachConcentrationArray objectAtIndex:i]
andConstant:bleachConstantArray[i]
andIsLiquid:YES];
[bleachArray addObject:bleachChemical];
NSLog(#"bleachChemical: chemName = %#, chemConcentration = %#, chemConstant = %1.6f, chemIsLiquid = %d", bleachChemical.chemName, bleachChemical.chemConcentration, bleachChemical.chemConstant, bleachChemical.chemIsLiquid);
[bleachChemical release];
}
bleachConcentrationArray = nil;
// Sets up the array for the Trichlor key
NSMutableArray *trichlorArray = [[NSMutableArray alloc] init];
Chemical *trichlorChemical = [[Chemical alloc] initWithChemical:#"Trichlor"
andConcentration:#"90%"
andConstant:0.0001480
andIsLiquid:NO];
[trichlorArray addObject:trichlorChemical];
NSLog(#"trichlorChemical: chemName = %#, chemConcentration = %#, chemConstant = %1.6f, chemIsLiquid = %d", trichlorChemical.chemName, trichlorChemical.chemConcentration, trichlorChemical.chemConstant, trichlorChemical.chemIsLiquid);
[trichlorChemical release];
// Sets up the array for the Dichlor key
NSMutableArray *dichlorArray = [[NSMutableArray alloc] init];
NSArray *dichlorConcentrationArray = [[NSArray alloc] initWithObjects:#"56%", #"62%", nil];
float dichlorConstantArray[] = {0.0002400, 0.0002168};
for (int i=0; i<2; i++) {
Chemical *dichlorChemical = [[Chemical alloc] initWithChemical:#"Dichlor"
andConcentration:[dichlorConcentrationArray objectAtIndex:i]
andConstant:dichlorConstantArray[i]
andIsLiquid:NO];
[dichlorArray addObject:dichlorChemical];
NSLog(#"dichlorChemical: chemName = %#, chemConcentration = %#, chemConstant = %1.6f, chemIsLiquid = %d", dichlorChemical.chemName, dichlorChemical.chemConcentration, dichlorChemical.chemConstant, dichlorChemical.chemIsLiquid);
[dichlorChemical release];
}
dichlorConcentrationArray = nil;
// Sets up the array for the Cal Hypo key
NSMutableArray *calHypoArray = [[NSMutableArray alloc] init];
NSArray *calHypoConcentrationArray = [[NSArray alloc] initWithObjects:#"48%", #"53%", #"65", #"73", nil];
float calHypoConstantArray[] = {0.0002817, 0.0002551, 0.0002080, 0.0001852};
for (int i=0; i<2; i++) {
Chemical *calHypoChemical = [[Chemical alloc] initWithChemical:#"Cal Hypo"
andConcentration:[calHypoConcentrationArray objectAtIndex:i]
andConstant:calHypoConstantArray[i]
andIsLiquid:NO];
[calHypoArray addObject:calHypoChemical];
NSLog(#"calHypoChemical: chemName = %#, chemConcentration = %#, chemConstant = %1.6f, chemIsLiquid = %d", calHypoChemical.chemName, calHypoChemical.chemConcentration, calHypoChemical.chemConstant, calHypoChemical.chemIsLiquid);
[calHypoChemical release];
}
calHypoConcentrationArray = nil;
// Sets up the array for the Li Hypo key
NSMutableArray *liHypoArray = [[NSMutableArray alloc] init];
Chemical *liHypoChemical = [[Chemical alloc] initWithChemical:#"Li Hypo"
andConcentration:#"90%"
andConstant:0.0003800
andIsLiquid:NO];
[liHypoArray addObject:liHypoChemical];
NSLog(#"liHypoChemical: chemName = %#, chemConcentration = %#, chemConstant = %1.6f, chemIsLiquid = %d", liHypoChemical.chemName, liHypoChemical.chemConcentration, liHypoChemical.chemConstant, liHypoChemical.chemIsLiquid);
[liHypoChemical release];
// The array of keys for the chlorine chemicals
NSArray *chlorineKeys = [[NSArray alloc] initWithObjects:#"Bleach", #"Trichlor", #"Dichlor", #"Cal Hypo", #"Li Hypo", nil];
// The array of values for the chlorine chemicals
NSArray *chlorineValues = [[NSArray alloc] initWithObjects:bleachArray, trichlorArray, dichlorArray, calHypoArray, liHypoArray, nil];
[bleachArray release];
[trichlorArray release];
[dichlorArray release];
[calHypoArray release];
[liHypoArray release];
// The dictionary to hold the arrays of chlorine chemical objects
NSDictionary *chlorineDictionary = [[NSDictionary alloc] initWithObjects:chlorineValues forKeys:chlorineKeys];
[chlorineValues release];
[chlorineKeys release];
return chlorineDictionary;
}
EDIT: Changed name from generateCYADictionary to newCYADictionary
Removed a release that happened after the return
- (id)newCYADictionary {
// Sets up the array for the CYA Granules key
NSMutableArray *cyaGranulesArray = [[NSMutableArray alloc] init];
Chemical *cyaGranulesChemical = [[Chemical alloc] initWithChemical:#"CYA Granules"
andConcentration:#""
andConstant:0.0001330
andIsLiquid:NO];
[cyaGranulesArray addObject:cyaGranulesChemical];
NSLog(#"cyaGranulesChemical: chemName = %#, chemConcentration = %#, chemConstant = %1.6f, chemIsLiquid = %d", cyaGranulesChemical.chemName, cyaGranulesChemical.chemConcentration, cyaGranulesChemical.chemConstant, cyaGranulesChemical.chemIsLiquid);
[cyaGranulesChemical release];
// Sets up the array for the Liquid Stabilizer key
NSMutableArray *liquidStabilizerArray = [[NSMutableArray alloc] init];
Chemical *liquidStabilizerChemical = [[Chemical alloc] initWithChemical:#"Liquid Stabilizer"
andConcentration:#""
andConstant:0.0003460
andIsLiquid:YES];
[liquidStabilizerArray addObject:liquidStabilizerChemical];
NSLog(#"liquidStabilizerChemical: chemName = %#, chemConcentration = %#, chemConstant = %1.6f, chemIsLiquid = %d", liquidStabilizerChemical.chemName, liquidStabilizerChemical.chemConcentration, liquidStabilizerChemical.chemConstant, liquidStabilizerChemical.chemIsLiquid);
[liquidStabilizerChemical release];
// The array of keys for the CYA chemicals
NSArray *cyaKeys = [[NSArray alloc] initWithObjects:#"CYA Granules", #"Liquid Stabilizer", nil];
// The array of values for the CYA chemicals
NSArray *cyaValues = [[NSArray alloc] initWithObjects:cyaGranulesArray, liquidStabilizerArray, nil];
[cyaGranulesArray release];
[liquidStabilizerArray release];
// The dictionary to hold the arrays of CYA chemical objects
NSDictionary *cyaDictionary = [[NSDictionary alloc] initWithObjects:cyaValues forKeys:cyaKeys];
[cyaKeys release];
[cyaValues release];
return cyaDictionary;
}
Replace the
return cyaDictionary;
[cyaDictionary release];
With
return [cyaDictionary autorelease];
Or, you might replace the
NSDictionary *chlorineDictionary = [[NSDictionary alloc] initWithObjects:chlorineValues forKeys:chlorineKeys];
With
NSDictionary *chlorineDictionary = [NSDictionary dictionaryWithObjects:chlorineValues forKeys:chlorineKeys];
Instead of adding the autorelease.
In your original implementation the [cyaDictionary release]; is never executed (because it is after return).
You can use this dictionary outside this method and you shouldn't release it there.
You might want also return a retained object (without the autorelease) and release it outside the method. In this case you should start the method name with "new" or "alloc"...
EDIT (Important):
You should use only one of my suggestions.
Use the autorelease in the return line
Use the dictionaryWith...
Add the "new" or "alloc" prefix in the method name and release the returned object outside this method.
If you replace the alloc init with dictionaryWith... then you get an autoreleased object. And then, if you release it in the outer method then you have a serious problem (the object will try to release itself after the current runloop of the thread and it may crash the app because the object will already be released by you).
EDIT (due to one of the comments)
If you want to create a property that will return a dictionary:
// MyClass.h file
#interface MyClass : NSObject {
..
NSDictionary *_dict1;
..
}
#property (nonatomic, retain) NSDictionary *dict1;
..
#end
// MyClass.m file
#implementation MyClass
#synthesize dict1 = _dict1;
..
- (NSDictionary *)dict1 {
if (_dict1 == nil) {
NSDictionary *dict1Temp = [NSDictionary new];
// Your implementation goes here...
self.dict1 = dict1Temp;
[dict1Temp release];
}
}
..
- (void)dealloc {
[_dict1 release];
[suoer dealloc];
}
#end