Saved data getting replaced by new data on app relaunch - ios

I am making a calorie counter which displays the total calorie count of various foods added. I have written code to save data following this tutorial. When I relaunch the app I can see the calorie count is the same as when I quit the app but when I add a new food item, the calorie count is reset and the count begins from the start. Why is the value not being saved??
EDIT:
This is a snippet of my code:
if(alertView.tag == ChickenAlertView) {
NSString *buttonTitle = [alertView buttonTitleAtIndex:buttonIndex];
if([buttonTitle isEqualToString:#"Ok"]){
float chicken= ([ChickenText.text floatValue]);
currentnumber = (chicken/100)*219;
result = result + currentnumber;
calories.text= [[NSString alloc] initWithFormat:#"%.f",result];
}
}
From NSLog, i can see the value of result is going to 0 every time I relaunch the app. How do I prevent it?
This is where I save the code:
- (NSString *) saveFilePath {
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [[path objectAtIndex:0] stringByAppendingPathComponent:#"savefile.plist"];
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
NSArray *values = [[NSArray alloc] initWithObjects: NameLabel.text, AgeLabel.text, HeightLabel.text, WeightLabel.text, BMILabel.text, calories.text, [NSNumber numberWithFloat:result], nil];
[values writeToFile:[self saveFilePath] atomically:YES];
[values release];
}
- (void)viewDidLoad
{
foodData = [[foodData alloc]init];
NSString *myPath = [self saveFilePath];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:myPath];
if (fileExists)
{
NSArray *values = [[NSArray alloc] initWithContentsOfFile:myPath];
NameLabel.text = [values objectAtIndex:0];
AgeLabel.text = [values objectAtIndex:1]
HeightLabel.text = [values objectAtIndex:2];
WeightLabel.text = [values objectAtIndex:3];
BMILabel.text = [values objectAtIndex:4];
calories.text = [values objectAtIndex:5];
result = [[values objectAtIndex:6] floatValue];
[values release];
}
UIApplication *myApp = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:myApp];
[super viewDidLoad];
}

Related

Does CHCSVParser have a column parsing limit?

In my application you can import data through a tab separated values file. I don't have any challenge until I parse "locations" that have multiple items attached to them. If you scroll to the very bottom of the second method you can see how I create a relationship between items and the locations that contain them inside Core Data. The problem occurs when I parse past column 31 in a location. It doesn't attach those items to the location. So my question is this; is there a limit to columns in the NSArray that is parsed by CHCSVParser? If not, what would cause this limiting to 31 columns?
I've posted the two methods that I encounter the bug with below.
+ (void) importDatabaseTSVURL:(NSURL*)url {
// First check if there is already a database. If so, stop import.
if ([XSELLocation locations].count > 0) return;
if ([XSELItem items].count > 0) return;
if ([XSELVendor vendors].count > 0) return;
NSError *error;
NSArray *array = [NSArray arrayWithContentsOfDelimitedURL:url options:CHCSVParserOptionsSanitizesFields delimiter:'\t' error:&error];
if ([[[array firstObject] firstObject] isEqualToString:#"XSELINVENTORYTSV"]) {
for (NSArray *row in array) {
[XSELSettings parseImportDataRow:row];
}
}
}
+ (void) parseImportDataRow:(NSArray*)array {
// Create logic to seperate data entered next
static NSString *operation = #"none";
if ([array.firstObject isEqualToString:#"ITEMLIST"]) {
operation = #"items";
return;
}
else if ([array.firstObject isEqualToString:#"LOCATIONLIST"]) {
operation = #"locations";
return;
}
else if ([array.firstObject isEqualToString:#"VENDORLIST"]) {
operation = #"vendors";
return;
}
else if ([array.firstObject isEqualToString:#"ENDLIST"]) { // Create database, relate objects, and clean up the data
operation = #"none";
return;
}
// Parse rows to the correct array.
if ([operation isEqualToString:#"vendors"]) {
NSLog(#"adding vendor");
XSELVendor *vendor = [XSELVendor addVendor];
vendor.vendorID = [NSNumber numberWithInteger:[[array objectAtIndex:0] integerValue]];
[XSELSettings nextVendorID];
vendor.name = [array objectAtIndex:1];
vendor.contactID = [array objectAtIndex:2];
}
else if ([operation isEqualToString:#"items"]) {
NSLog(#"adding item");
XSELItem *item = [XSELItem addItem];
item.itemID = [NSNumber numberWithDouble:[[array objectAtIndex:0] integerValue]];
[XSELSettings nextItemID];
item.name = [array objectAtIndex:1];
item.smallPackageName = [array objectAtIndex:2];
item.bigPackageName = [array objectAtIndex:3];
item.smallPerBig = [NSNumber numberWithDouble:[[array objectAtIndex:4] integerValue]];
item.buildTo = [NSNumber numberWithDouble:[[array objectAtIndex:5] integerValue]];
item.price = [NSNumber numberWithDouble:[[array objectAtIndex:6] integerValue]];
// Relate preferred vendor to item
for (XSELVendor *vendor in [XSELVendor vendors]) {
if ([vendor.vendorID.stringValue isEqualToString:[array objectAtIndex:7]]) {
item.preferredVendor = vendor;
break;
}
}
}
else if ([operation isEqualToString:#"locations"]) {
NSLog(#"adding location");
XSELLocation *location = [XSELLocation addLocation:[array objectAtIndex:1]];
location.locationID = [NSNumber numberWithInteger:[[array objectAtIndex:0] integerValue]];
[XSELSettings nextLocationID];
location.position = [NSNumber numberWithInteger:[[array objectAtIndex:2] integerValue]];
// Relate location with items
unsigned long itemsRelatedCount = array.count - 3;
NSLog(#"\n\nitemsRelated: %lu\n\n", itemsRelatedCount);
NSMutableOrderedSet *items = [NSMutableOrderedSet orderedSet];
for (int i = 0; i < itemsRelatedCount; i++) {
NSString *itemID = [array objectAtIndex:i];
for (XSELItem *item in [XSELItem items]) {
if ([item.itemID.stringValue isEqualToString:itemID]) {
[items addObject:item];
break;
}
}
}
location.items = items;
}
}

Multiple methods named 'objectAtIndex:' found with mismatched result, parameter type or attributes

I have a table on my ios app that shows last tweets, however after updating my app to 64bit architecture I'm getting four times the following error: multiple methods named 'objectAtIndex:' found with mismatched result, parameter type or attributes error.
This is the relevant part of the code:
-(void)tableView:(UITableView*)tableView didHoldRowAtIndexPath:(NSIndexPath*)indexPath {
if ([NXCatchall isiPad]) {
NSDictionary *tweet = [twitterHandler getTweetForArrayIndex:indexPath.row];
NSDictionary *urls = [[tweet objectForKey:#"entities"] objectForKey:#"urls"];
urlDict = [NSMutableDictionary dictionary];
for (int i=0; i<urls.count; i++) {
NSString *displayName = [[urls valueForKey:#"display_url"] objectAtIndex:i];
NSURL *url = [NSURL URLWithString:[[urls valueForKey:#"expanded_url"]objectAtIndex:i]];
[urlDict setValue:url forKey:displayName];
}
if (urlDict.count != 0) {
UIActionSheet *actionSheet = [[UIActionSheet alloc] init];
[actionSheet setTitle:#"Open in Safari"];
[actionSheet setDelegate:self];
for (int i=0; i<urlDict.count; i++) {
// NSString *key = [[dict allKeys] objectAtIndex:i];
//Yes it's ugly, it works at runtime. Deal with it.
[actionSheet addButtonWithTitle:[[urlDict valueForKey:(NSString*)
[[urlDict allKeys]objectAtIndex:i]]absoluteString]];
}
[[NSNotificationCenter defaultCenter] postNotificationName:#"heldTweetWithInfo" object:self userInfo:[NSDictionary dictionaryWithObject:actionSheet forKey:#"actionSheet"]];
}
}
}
#pragma mark - Table view delegate
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *tweet = [twitterHandler getTweetForArrayIndex:indexPath.row];
if ([NXCatchall isiPad]) {
[[NSNotificationCenter defaultCenter] postNotificationName:#"selectedTweetNotification" object:self userInfo:tweet];
}
NSDictionary *urls = [[tweet objectForKey:#"entities"] objectForKey:#"urls"];
urlDict = [NSMutableDictionary dictionary];
for (int i=0; i<urls.count; i++) {
NSString *displayName = [[urls valueForKey:#"display_url"] objectAtIndex:i];
NSURL *url = [NSURL URLWithString:[[urls valueForKey:#"expanded_url"]objectAtIndex:i]];
[urlDict setValue:url forKey:displayName];
}
Affected lines start with NSString & NSURL
Try casting it into NSArray. My guess is that some other class declares objectAtIndex.
NSString *displayName = [(NSArray *)[urls valueForKey:#"display_url"] objectAtIndex:i];
NSURL *url = [NSURL URLWithString:[(NSArray *)[urls valueForKey:#"expanded_url"]objectAtIndex:i]];

saving simple values in iOS leads to a large documents and data file

I am developing a simple iOS game and my app size is only 3 mb
this is the code I use to save the users high scores
the problem is that every time I use the app, its documents and data file size increases. it reached 28 mb on my iPad. why is this happening ?
any help is appreciated
- (void)applicationDidEnterBackground:(UIApplication *)application{
NSArray *value = [[NSArray alloc]initWithObjects:[NSNumber numberWithFloat:easyHighscoreFloat],[NSNumber numberWitFloat:normalHighscoreFloat],[NSNumber numberWithFloat:hardHighscoreFloat],nil];
[value writeToFile:[self saveHighScore] atomically:YES];
}
-(NSString*)saveHighScore{
NSArray *filePath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [[filePath objectAtIndex:0]stringByAppendingPathComponent:#"savedState.plist"];
}
- (void)viewDidLoad{
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:[UIApplication sharedApplication]];
NSString *path = [self saveHighScore];
BOOL fileExists = [[NSFileManager defaultManager]fileExistsAtPath:path];
if (fileExists) {
NSArray *loadValues = [[NSArray alloc]initWithContentsOfFile:path];
easyHighscoreFloat = [[loadValues objectAtIndex:0]floatValue];
normalHighscoreFloat = [[loadValues objectAtIndex:1]floatValue];
hardHighscoreFloat = [[loadValues objectAtIndex:2]floatValue];
}else{
easyHighscoreFloat = 0;
normalHighscoreFloat = 0;
hardHighscoreFloat = 0;
}
}

iOS Adding Array to Plist Document Root

Okay so after feedback I am doing this changes to my code it's working but just adding and replacing the first one?
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *user_id = [prefs objectForKey:#"user_id"];
NSString *fixture_id = [prefs objectForKey:#"fixture_id"];
// Get path to documents directory
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
if ([paths count] > 0)
{
NSString *selectedPath = [[paths objectAtIndex:0]
stringByAppendingPathComponent:[NSString stringWithFormat:#"%#-%#",user_id, fixture_id]];
// Read both back in new collections
self.mySelectionsArray = [NSArray arrayWithContentsOfFile:selectedPath];
NSLog(#"Players Selected = %#", self.mySelectionsArray);
}
NSDictionary *tempDic = [[[self.listOfPlayersArray objectAtIndex:indexPath.section] objectForKey:#"contacts"] objectAtIndex:indexPath.row];
NSString *avatar = [tempDic objectForKey:#"avatar"];
NSString *avatarSmall = [tempDic objectForKey:#"avatar_small"];
NSString *first_name = [tempDic objectForKey:#"first_name"];
NSString *last_name = [tempDic objectForKey:#"last_name"];
NSDictionary *innerDic;
innerDic = [NSDictionary dictionaryWithObjects:
[NSArray arrayWithObjects: avatar, avatarSmall, first_name, last_name, nil]
forKeys:[NSArray arrayWithObjects:#"avatar", #"avatar_small", #"first_name", #"last_name", nil]];
self.mySelectionsArray = [NSMutableArray arrayWithObject:[NSDictionary dictionaryWithDictionary:innerDic]];
// [self.mySelectionsArray insertObject:innerDic atIndex:0];
[self.mySelectionsArray addObject:innerDic];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if ([paths count] > 0)
{
// Path to save array data
NSString *arrayPath = [[paths objectAtIndex:0]
stringByAppendingPathComponent:[NSString stringWithFormat:#"%#-%#",user_id, fixture_id]];
NSLog(#"Path: %#",arrayPath);
// Write array
[self.mySelectionsArray writeToFile:arrayPath atomically:YES];
}
[self dismissViewControllerAnimated:YES completion:nil];
}
Which is now checking for array and pulling it down then adding the object
The plist looks like this after selecting a player;
{
"first_name" = Ollie;
"last_name" = Akroyd;
},
{
"first_name" = Ollie;
"last_name" = Akroyd;
}
)
Stated your code, mySelections is empty, I guess you want to add innerDic to it; moreover you are saving mySelections instead of userSelections.
You should add innerDic to mySelections and save userSelections to resolve your issue.
EDIT
Instead of
self.mySelectionsArray = [NSMutableArray arrayWithObject:[NSDictionary dictionaryWithDictionary:innerDic]];
which overrides the read array, add the object:
[self.mySelectionsArray addObject:innerDic];
self.mySelectionsArray must be mutable, so instead of
self.mySelectionsArray = [NSArray arrayWithContentsOfFile:selectedPath];
write
self.mySelectionsArray = [[NSArray arrayWithContentsOfFile:selectedPath] mutableCopy];

NSMutableArray Add and Save Objects

New to iOS and am stuck on one issue in regards to adding objects in NSMutable Array and displaying the array on another view within the App. The data displays fine on other view in TableView, but when I add another item to the Array (using code below), it just replaces what was there, not adding to the array.
- (void) postArray {
tableData = [[NSMutableArray alloc] initWithCapacity:10];
tableData = [[NSMutableArray alloc] initWithObjects: nil];
[tableData addObject:favShot]; }
-(NSString *) saveFilePath {
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, TRUE);
return [[path objectAtIndex:0] stringByAppendingPathComponent:#"savefile.plist"]; }
- (void) viewWillDisappear:(BOOL)animated: (UIApplication *) application {
NSArray *values = [[NSArray alloc] initWithObjects:tableData, nil];
[values writeToFile:[self saveFilePath] atomically: TRUE]; }
- (void)viewDidLoad {
tableData = [[NSMutableArray alloc] initWithObjects: nil];
NSString *myPath = [self saveFilePath];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:myPath];
if (fileExists)
{
NSArray *values = [[NSArray alloc] initWithContentsOfFile:myPath];
tableData = [values mutable copy];
}
UIApplication *myApp = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:myApp];
[super viewDidLoad]; }
Thank you.
Every time you call postArray you're creating an instance of NSMutableArray, then throwing it away (leaking it if you aren't using ARC). Then you're creating another instance of NSMutableArray. Then you're adding an object (favShot) to that second instance.
Next time you call postArray it's going to throw away your old array and create 2 new ones.
What you want to do is create the tableData instance when you create the controller instance, or when the view loads. Then, don't set tableData = ... as that will discard the old instance. Just add and remove objects.
edit
- (void) postArray {
[tableData addObject:favShot];
}
- (NSString *)saveFilePath {
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, TRUE);
return [[path objectAtIndex:0] stringByAppendingPathComponent:#"savefile.plist"];
}
- (void) viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[tableData writeToFile:[self saveFilePath] atomically: TRUE];
}
- (void)viewDidLoad {
NSString *myPath = [self saveFilePath];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:myPath];
if (fileExists)
{
tableData = [[NSMutableArray alloc] initWithContentsOfFile:myPath];
} else {
tableData = [[NSMutableArray alloc] initWithObjects: nil];
}
UIApplication *myApp = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:myApp];
[super viewDidLoad];
}
Try
- (void) viewWillDisappear:(BOOL)animated: (UIApplication *) application
{
NSString *filePath = [self saveFilePath];
NSMutableArray *savedArray = [NSMutableArray arrayWithContentsOfFile:filePath];
if (!savedArray) savedArray = [NSMutableArray array];
[savedArray addObject:tableData];
[savedArray writeToFile:filePath atomically:YES];
}

Resources