Save several ints to array and show total value in a label - iphone

What I like to do:
User enters 10 in UITextField and tap on UIButton.
UILabel shows 10 and UITextField goes blank.
User enters 5 in UITextField and tap on UIButton.
UILable shows 15 and UITextField goes blank again.
With following code I get the entered number saved and shown in the label but how can I tell the array to add and show me total and not just the very first number I entered?
h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (nonatomic, strong) IBOutlet UILabel *label;
#property (nonatomic, strong) IBOutlet UITextField *field;
#property (nonatomic, strong) NSString *dataFilePath;
#property (nonatomic, strong) NSString *docsDir;
#property (nonatomic, strong) NSArray *dirPaths;
#property (nonatomic, strong) NSFileManager *fileMgr;
#property (nonatomic, strong) NSMutableArray *array;
- (IBAction)saveNumber:(id)sender;
#end
m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize label, field, dataFilePath, docsDir, fileMgr, dirPaths, array;
- (void)viewDidLoad
{
[super viewDidLoad];
fileMgr = [NSFileManager defaultManager];
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
dataFilePath = [[NSString alloc]initWithString:[docsDir stringByAppendingPathComponent:#"data.archive"]];
if ([fileMgr fileExistsAtPath:dataFilePath])
{
array = [NSKeyedUnarchiver unarchiveObjectWithFile:dataFilePath];
self.label.text = [array objectAtIndex:0];
}
else
{
array = [[NSMutableArray alloc] init];
}
}
- (IBAction)saveNumber:(id)sender
{
[array addObject:self.field.text];
[NSKeyedArchiver archiveRootObject:array toFile:dataFilePath];
[field setText:#""];
[label setText:[array objectAtIndex:0]];
}

You need to iterate through all the values and add them to a running total. Have a look at this:-
- (IBAction)saveNumber:(id)sender
{
[array addObject:self.field.text];
[NSKeyedArchiver archiveRootObject:array toFile:dataFilePath];
[field setText:#""];
// Create an enumerator from the array to easily iterate
NSEnumerator *e = [array objectEnumerator];
// Create a running total and temp string
int total = 0;
NSString stringNumber;
// Enumerate through all elements of the array
while (stringNumber = [e nextObject]) {
// Add current number to the running total
total += [stringNumber intValue];
}
// Now set the label to the total of all numbers
[label setText:[NSString stringWithFormat:#"%d",total];
}
I've commented the code for readability.

Iterate over the array, get all values as numbers using [string intValue] and sum them up in another variable. Then add the calculated value to the label using a formatted string like [NSString stringWithFormat: #"%d"].

Related

NSMutableArray is not maintaining data [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
I have created a custom class for EmployeeInfo:
#interface METEmployee : NSObject
#property (weak, nonatomic) NSString *EmpNo;
#property (weak, nonatomic) NSString *FirstName;
#property (weak, nonatomic) NSString *MiddleName;
#property (weak, nonatomic) NSString *LastName;
#property (weak, nonatomic) NSString *Department;
#property (weak, nonatomic) NSString *HireDate;
#property (weak, nonatomic) NSString *JobTitle;
#property (weak, nonatomic) NSString *SupervisorNumber;
#property (weak, nonatomic) NSString *SupLastName;
#property (weak, nonatomic) NSString *SupFirstName;
#property (weak, nonatomic) NSString *MobilePhone;
#property (weak, nonatomic) NSString *EmailAddress;
#property (weak, nonatomic) NSString *DeskPhone;
#property (weak, nonatomic) NSString *EmployeeType;
#property (weak, nonatomic) NSString *Location;
#end
Then in my view controller.h I have created:
NSMutableArray *theemplyees;
#property(nonatomic, retain) NSMutableArray *theemplyees;
Synthesize is .m:
#synthesize theemplyees
Then in ViewDidLoad, init and call to populate it:
theemplyees = [[NSMutableArray alloc] init];
[self getEmps];
In getEmps, I add the records to the array:
results = [database executeQuery:#"select * from EmpInfo order by LastName"];
while([results next]) {
METEmployee *empInfo = [METEmployee alloc];
empInfo.EmpNo = [results stringForColumn:#"EmpNo"];
empInfo.FirstName = [results stringForColumn:#"FirstName"];
empInfo.MiddleName = [results stringForColumn:#"MiddleName"];
empInfo.LastName = [results stringForColumn:#"LastName"];
empInfo.Department = [results stringForColumn:#"Department"];
empInfo.HireDate = [results stringForColumn:#"HireDate"];
empInfo.JobTitle = [results stringForColumn:#"JobTitle"];
empInfo.SupervisorNumber = [results stringForColumn:#"SupervisorNumber"];
empInfo.SupFirstName = [results stringForColumn:#"SupFirstName"];
empInfo.SupLastName = [results stringForColumn:#"SupLastName"];
empInfo.MobilePhone = [results stringForColumn:#"MobilePhone"];
empInfo.EmailAddress = [results stringForColumn:#"EmailAddress"];
empInfo.DeskPhone = [results stringForColumn:#"DeskPhone"];
empInfo.EmployeeType = [results stringForColumn:#"EmployeeType"];
empInfo.Location = [results stringForColumn:#"Location"];
[theemplyees addObject:empInfo];
}
Everything works fine for populating the table for the the first screen full of records:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
METEmpTableViewCell *cell = (METEmpTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"myCell"];
cell.lblFirstName.text = [[theemplyees objectAtIndex:indexPath.row] valueForKey:#"FirstName"];
cell.lblLastName.text = [[theemplyees objectAtIndex:indexPath.row] valueForKey:#"LastName"];
cell.lblDepartment.text = [[theemplyees objectAtIndex:indexPath.row] valueForKey:#"Department"];
NSString* picName = [NSString stringWithFormat:#"%#.jpg", [[theemplyees objectAtIndex:indexPath.row] valueForKey:#"EmpNo"]];
#try {
cell.empPicture.image = [UIImage imageNamed:picName];
}
#catch (NSException *exception) {
}
#finally {
}
return cell;
}
But if I attempt to scroll up or down on the Tableview, the array says the data is null...although it still shows the record count. If I resize my cell pn the table to smaller, it will populate more rows (that are visible) but once again any scrolling and they are gone.
Any thoughts or sugguestions is greatly appreciated. Thanks in advance for any and all help!
Geo...
You all have weak properties which means that all of the strings are instantly deallocated, since nothing is retaining them. Change it to this and try:
#property (nonatomic, strong) NSString *theString;
Also, you want to initialize your NSMutableArray like so (you're missing the init method):
NSMutableArray *array = [[NSMutableArray alloc] init];

NSMutableArray or NSArray structures

In NSMutableArray or NSArray how do you set up the row structure. All the examples I can find just deal with one dimensional integers or strings.
So how do you go about setting up an array row structure like:
Integer, String, Date
You would need to create an array of arrays, or an array of dictionaries, the second approach being better if you'd like to refer to the data by name rather than index:
NSMutableArray *rows = [[NSMutableArray alloc] init];
NSMutableDictionary *firstRow = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:12], #"fieldWithNumber",
[NSString stringWithFormat:#"A formatted string %ld", 34], #"fieldWithString",
[NSDate date], #"fieldWithDate",
nil];
[rows addObject:firstRow];
// etc.
You can make custom class and add collection of these objects in an array.
For example please assume that we have to do some rows about places then create a class PLACE.h
#interface PLACE : NSObject
{
NSString *title;
NSString *summary;
NSString *url;
NSString *latitude;
NSString *longitude;
}
#property (nonatomic, retain) NSString *title;
#property (nonatomic, retain) NSString *summary;
#property (nonatomic, retain) NSString *url;
#property (nonatomic, retain) NSString *latitude;
#property (nonatomic, retain) NSString *longitude;
#end
PLACE.m
#implementation PLACE
#synthesize title;
#synthesize summary;
#synthesize url;
#synthesize latitude;
#synthesize longitude;
- (void) dealloc
{
[title release];
[summary release];
[url release];
[latitude release];
[longitude release];
[super dealloc];
}
#end
Create instance of the class PLACE for each place and hold the objects in the array. I think that solves your problem.
An array is just a collection of objects.
Just create an object that has an integer, date and string and then add instances of those to the array.

Leaky Custom Object for storing data from a plist

I have made a very simple custom object pictureData.
Here is the .h file
#import <Foundation/Foundation.h>
#interface pictureData : NSObject {
NSString *fileName;
NSString *photographer;
NSString *title;
NSString *license;
}
#property (nonatomic, retain) NSString *fileName;
#property (nonatomic, retain) NSString *photographer;
#property (nonatomic, retain) NSString *title;
#property (nonatomic, retain) NSString *license;
+(pictureData*)picDataWith:(NSDictionary*)dictionary;
#end
The .m file
#import "pictureData.h"
#implementation pictureData
#synthesize fileName;
#synthesize photographer;
#synthesize title;
#synthesize license;
+ (pictureData*)picDataWith:(NSDictionary *)dictionary {
pictureData *tmp = [[[pictureData alloc] init] autorelease];
tmp.fileName = [dictionary objectForKey:#"fileName"];
tmp.photographer = [dictionary objectForKey:#"photographer"];
tmp.title = [dictionary objectForKey:#"title"];
tmp.license = [dictionary objectForKey:#"license"];
return tmp;
}
-(void)dealloc {
[fileName release];
[photographer release];
[title release];
[license release];
}
#end
I then set up these objects in an array, like so:
NSString *path = [[NSBundle mainBundle] pathForResource:#"pictureLicenses" ofType:#"plist"];
NSArray *tmpDataSource = [NSArray arrayWithContentsOfFile:path];
NSMutableArray *tmp = [[NSMutableArray alloc] init];
self.dataSource = tmp;
[tmp release];
for (NSDictionary *dict in tmpDataSource) {
pictureData *pic = [pictureData picDataWith:dict];
NSLog(#"%#", pic.title);
[self.dataSource addObject:pic];
}
Everything works smashingly. I have a table view which loads the proper picture images, and information, no problem. Upon running Instruments for leaks, I see that my pictureData object is leaks with every allocation.
I would assume that with having my object autoreleased I would not have to worry about manually allocating and deallocating them.
Perhaps is my issue that I use autorelease, which the autoReleasePool keeps a retain count of +1 and then when I add a pictureData object to my array, that also retains it? Thank you all for your time!
edit: Don't forget to call super! Thank you Sam!
Change dealloc to:
-(void)dealloc {
[fileName release];
[photographer release];
[title release];
[license release];
[super dealloc];
}
(call [super dealloc])
In your function, change the return value to include autorelease, like
+ (pictureData*)picDataWith:(NSDictionary *)dictionary
{
...
...
return [tmp autorelease];
}
When you add pictureData object to dataSource, you increase the retain count, so you should autorelease it while returning.
Hope it helps.

NSArray With NSString Is This Even Possible?

I am trying to build a Grouped Sectioned View. I want to set an array as an object in the dictionary but I came across the empty array Issues.
Is this Even possible????? Is There a trick ????
#import "RootViewController.h"
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// Get the specific Node for this row.
Nodes *nodes = (Nodes *)[nodesMArray objectAtIndex:indexPath.row];
// Create the Details View Controller and initialize it.
nodesDetailView *viewController = [[nodesDetailView alloc] initWithStyle:UITableViewStyleGrouped ];
[[self navigationController] pushViewController:viewController animated:YES];
// Set the title of the view to the nodes name
viewController.title = [nodes computer_name];
//Information
//Network Data
viewController.ipaddress= [nodes ipaddress];
viewController.subnet_mask= [nodes subnet_mask];
viewController.gateway= [nodes gateway];
viewController.domain_name= [nodes domain_name];
}
#import "nodesDetailViewController. h
#interface nodesDetailView : UITableViewController{
//Network Data
NSString *ipaddress;
NSString *subnet_mask;
NSString *gateway;
NSString *domain_name;
//Grouped
NSMutableArray *Keys;
NSMutableDictionary *Contents;
}
#property (nonatomic, retain) NSMutableArray *Keys;
#property (nonatomic, retain) NSMutableDictionary *Contents;
#property (nonatomic, retain) NSString *ipaddress;
#property (nonatomic, retain) NSString *subnet_mask;
#property (nonatomic, retain) NSString *gateway;
#property (nonatomic, retain) NSString *domain_name;
#end
#import "nodesDetailViewController. m
#synthesize .......
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
NSMutableArray *keys = [[NSMutableArray alloc] init];
NSMutableDictionary *contents = [[NSMutableDictionary alloc] init];
NSString *network = #"Network Data";
NSString *product = #"Product Details";
//IS THIS POSSIBLE ??????? Because I get An Empty array
[contents setObject:[NSArray arrayWithObjects: ipaddress,subnet_mask, gateway, domain_name, nil] forKey:network];
return self;
}
Thank You In Advance.
All of those strings that you are adding to the array haven't even been allocated/initialized yet. That's why the array is empty. You can't just go: NSString *emptyString; and then go: [myArray addObject:emptyString];. Your strings are all empty.
Check the values u are passing from the table view. They maybe nil. I just used this much of data and i m getting correct NSLog.
NSMutableDictionary *contents = [[NSMutableDictionary alloc] init];
NSString *my = #"kk";
NSString *my1 = #"polko";
[contents setObject:[NSArray arrayWithObjects: my1,my, nil] forKey:#"o"];
NSLog(#"%#" , contents);
For Those Who are wondering: Problem Solved My code was fine. the problem was :
it was in the wrong place.
The Code Supposed to be in - (void)viewDidLoad and not in - (id)initWithStyle:
I want to thank everybody who took the time to look in to it.
I have no idea why i put the code there to begin with.
Thanx Again

how to sort an NSMutableArray of Arrays?

I'm trying to sort an array of a table view with no luck, this is how I'm trying to do it:
- (void) compare
{
NSMutableArray *temp = [[NSMutableArray alloc] initWithObjects: nil];
[temp addObjectsFromArray:[self displayedObjects]];
int a = [[self displayedObjects] count];
for (int i = 0; i < (a - 1); i++){
for (int j = 0; j <= (i^2); j++) {
NSString *temp1 = [temp objectAtIndex:i];
NSString *temp2 = [temp objectAtIndex:i+1];
if (temp1 > temp2) {
[movieIndex replaceObjectAtIndex:i withObject:temp2];
[movieIndex replaceObjectAtIndex:i+1 withObject:temp1];
}
}
}
[self movieIndex];
[[self tableView] reloadData];
}
displayedObjects is an array of array that the user can add new objects. this objects are movie instances in form of:
The tableview cell has the title of the movie. "in" that title there is a tableview with details about the movie. What i want to do is sort the displayed movies titles in ascending order but my code doesn't seem to work.
displayedObjects is a set of 3 NSStrings and 1 NSNumber. It gets objects form the following class:
#import <Foundation/Foundation.h>
#interface Movie : NSObject
{
NSString *_title;
NSString *_gender;
NSString *_location;
NSNumber *_publicationYear;
}
#property (nonatomic, retain) NSString *location;
#property (nonatomic, retain) NSString *title;
#property (nonatomic, retain) NSString *gender;
#property (nonatomic, retain) NSNumber *publicationYear;
+ (id)movieWithTitle:(NSString *)title
gender:(NSString *)gender
year:(NSUInteger)year
location:(NSString *)location;
- (id)initWithTitle:(NSString *)title
gender:(NSString *)gender
year:(NSUInteger)year
location:(NSString *)location;
#end
Because no one has suggested it yet, and I personally love blocks, I'll suggest the block alternative to the same thing already suggested:
[myArray sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
...
}];
I made it work by using:
NSSortDescriptor *titleSorter= [[NSSortDescriptor alloc] initWithKey:#"title" ascending:YES];
[movieIndex sortUsingDescriptors:[NSArray arrayWithObject:titleSorter]];