Xcode: Saving an Int value [closed] - cocoa-touch

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 10 years ago.
I have a simple counter application, i.e. the user presses a button to increase it by a value of their choice. I started the application production on a single view application. I now have the need to make it so that when the app is closed it saves the last value of the counter. Then when the app reopens it needs to load the value of the counter back into place. The value needs to be saved and reloaded simply by closing and opening the app i.e. no buttons are needed to be pressed.
My counter variable is an Int value called counter. The view controllers are simply named viewController.h/m.
I have no idea how to set all of this up, I assume I need coreData to do this. How do I set up coreData? Do I code in my delegate of viewController? If this is not the best way to do it please provide a way to do it in a more effective way!
Thanks very much for any help, simple instructions appreciated most of all.
I have had a look at other example of this but none seemed to provide what I need or were simple enough to understand. Please provide an answer on this thread!
Hugh

It's easiest to simply use NSUserDefaults instead of Core Data.
To save:
[[NSUserDefaults standardUserDefaults] setInteger:counter forKey:#"counter"]
To read:
NSInteger counter = [[NSUserDefaults standardUserDefaults] integerForKey:#"counter"];
Take a look at UIApplicationDelegate to find what methods you should place the code in. It will likely be in your AppDelegate in one of the following methods:
Where to load the value:
-application:didFinishLaunchingWithOptions:
–applicationWillEnterForeground:
Where to save the value:
-applicationDidEnterBackground:
–applicationWillTerminate:
Exactly where depends on if you need to load and save the value when the user switches to another app, which is almost certainly the case as the app might be terminated when it is in a frozen state due to memory pressure. In this case you would want to make sure the value was saved when the app was backgrounded (the user switched to a different app) and the value was restored when the app became the foreground app (the user switched back to your app).

You can use NSUserDefaults.
You can store a variable creating an NSUserDefaults variable with
NSUserDefaults * standardUserDefaults = [NSUserDefaults standardUserDefaults];
Then save the integer with
[standardUserDefaults setInteger:1 forKey:#"integer"];
And synchronize all with [standardUserDefaults synchronize];
Then retrieve the integer creating a variable:
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
and then recover it with
NSInteger myInt = [standardUserDefaults integerForKey:#"integer"];

Related

Setting properties to objects in NSMutableArray [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.
Ok - can't quite make sense of what's going on here. I'm building a simple card game. I created a Category of UIView that handles all the stuff a "Card" should be. I figure this is irrelevant, but perhaps it's not.
Anyway, in my view controller, I'm just creating 2 NSMutableArrays to hold the dealer and players hands. Then I'm calling a method to set the card value. In that method, I do an NSLog to see the particular card object's value - and it all looks good. But if I try to get that value from my view controller, it always comes back for ALL the objects with the value of the last object in the array.
some code:
playersCards = [[NSMutableArray alloc] initWithObjects:[[UIView alloc] init],[[UIView alloc] init],nil];
[[playersCards objectAtIndex:0] setCardValue];
[[playersCards objectAtIndex:1] setCardValue];
NSLog(#"1: %i",[[playersCards objectAtIndex:0] returnValue]);
NSLog(#"2: %i",[[playersCards objectAtIndex:1] returnValue]);
So when I get the NSLog after calling setCardValue (this is within the Category) - again, all is fine. But those NSLogs right there - they return the value of index 1 for both. What's happening here?
There is no way that the setCardValue method can know what index the Card is at unless you are doing something convoluted. Therefore, it is likely that you do have two cards, but they are identically initialized.
However, there is a bigger problem here. You really don't want to use UIView instances as data like this. You really want to separate the bits that render stuff on screen [View] from the bits that hold the state of the game [model]. Typically there is a layer in between that manages the model state based on user interaction with the view [controller].
See the documentation on Model-View-Controller for more information.
Hanging stuff off of existing classes with categories may seem convenient, but it really shouldn't be used as the primary pattern for encapsulating data, state, and/or logic in your application.
You really want to keep that data [the game state] isolated from how the data is drawn on the screen [the views].
In terms of your specific question in your comment, another question:
Imagine that your code was written like this:
Card *c = [cardArray objectAtIndex: 0];
[c doSomething];
How would c know what index it is at in that code? Now, note that said code is identical to [[cardArray objectAtIndex:0] doSomething];.
If I were designing some kind of a Card game, I would likely create a handful of classes:
a Card class that simply stores a suit and value. Supports NSCoding for archival purposes.
a CardView subclass of UIView which, given a suit and value, knows how to render a card.
a GameFieldView and GameFieldController set of classes that know how to draw the playfield (former, UIView subclass) and how to move CardViews about the playfield (latter, a UIViewController)
specific subclasses of GameFieldController that add logic for things like hands, stacks, piles, and/or whatever else you might need to create a card game.
.... etc ....
That is, I'd break the game down into a series of classes that fit into the iOS or OS X model view controller patterns such that I'm writing a minimal amount of code and letting the system do the heavy lifting it is designed to do.
This may seem like overkill, what with all those classes and all, but, really, the individual classes are relatively simple and quite flexible.

Can't add a simple TableView to Storyboard [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 10 years ago.
Right now my StoryBoard is like this:
X->X->X
I want it to be like this:
X->Y->X->X
Y will be a simple Tableview connected to the navigation controller on one end and to masterviewcontroller on the other end with a basic cell pushing to it. I don't want to change anything in the app besides that.
but when I'm trying to do so I'm getting an error:
ScaryBugs[1768:11303] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITableViewController setBugs:]: unrecognized selector sent to instance 0x71d0940'
I'm guessing it's because I don't completely understand what those 3 lines are doing.
AppDelegate.m:
UINavigationController * navController = (UINavigationController *) self.window.rootViewController;
MasterViewController * masterController = [navController.viewControllers objectAtIndex:0];
masterController.bugs = bugs;
Source of code
That third line is just assigning the bugs property of the masterController to the array that was created in the app delegate with the local variable name, bugs. The first 2 lines are just getting references to the controllers that were created in the storyboard.
By putting another controller in as the root view controller of the navigation controller, you're screwing up the references. After adding it, the MasterController is now not even instantiated until you push to it, so there's no way to set its bugs property. Your new controller just doesn't belong there. It wouldn't really make sense to push from your list of bats, sharks, etc. to a list of bugs -- usually, that push (especially if it's from a table view cell) means you're going to present some information that gives more details about the cell you touched. IF you're trying to expand upon the tutorial, you really need to change the overall structure of the app, and that could require quite a few changes in the code.

AppDelegate int value keeps getting reset

In my project AppDelegate file, I have an int declared called correctAnswersCountR1. So in the app they take a small quiz and that variable keeps track of how many correct answers they got. Now somewhere else in the project I use this variable like so:
int r1score=appDelegate.correctAnswersCountR1;
The problem is that apparently if I exit the app and come back, the value isn't remembered, and is set back to its default value. How can I store this number so that it is remembered if the user closes the app and comes back?
You can use NSUserDefaults to store your value:
**Saving**
//Do this right before the app exits
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// saving an NSInteger
[prefs setInteger:42 forKey:#"integerKey"];
// This is suggested to synch prefs, but is not needed
[prefs synchronize];
**Retrieving**
//Do this when your app is loaded again
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// getting an NSInteger
NSInteger myInt = [prefs integerForKey:#"integerKey"];
You could set up core data for your project, though unless you plan on storing more information persistently for your app Core Data might be a bit of overkill. You could also try writing it to a file and just reading it on load.
Edit: For this specific scenario Oscar's answer seems more appropriate, though depending on where you plan on going with your app, CoreData or a file may be a good choice.
You'll want to do some research about NSUserDefaults.
Here is the apple documentation
On another note it's not considered best practice to store data in the AppDelegate
You have to use a preferences storing mechanism. I'm not all too familiar with the iPhone toolkit, but on Mac OS X and Cocoa there's NSUserDefaults. When your app launches, you would load the value from the user defaults (preferences) through [[NSUserDefaults standardUserDefaults] intForKey:#"count"], and whenever the value changes, you would call [[NSUserDefaults standardUserDefaults] setInt:answerCount... forKey:#"count"].
I'm pretty sure that you want to write the value into a file to make it persistent.
This is because an application which moved to the background might be terminated for example if the system measures out that it needs some more memory.
So it kills the application and restarts it when the user switches over.

Run a function only on second load of view

I am creating an iOS application which has a login system over a tab bar controller. The tab bar is loaded as the root controller and if the user is not logged in, a login subview fills the screen. Because the first view of the tab bar controller is already loaded, so is viewWillAppear:. I use viewWillAppear: to reload a table view on every load. The system works great.
However, I want to know how I can run a function (a void thing) on just the second load (ie. after the user has logged in), to provide a table view specific for the user rather than loading one on every view - this is why I am not using viewDidLoad:, as it only runs once.
Yeah, I have the much better & easy solution rather than taking some variable since the won't retain the last values when we restart our application.
For that you need to use Database but that takes to much of coding.So better to have NSUserDefaults which is used to store the system preferences.
Write this in your viewWillAppear:
if([[NSUserDefaults standardUserDefaults]valueforKey:#"key"]==nil)
{
NSUserDefaults *default = [NSUserDefaults standardUserDefaults];
[default setValue:#"1" forKey:#"key"];
[default synchronize];
}
else
{
NSLog(#"Once you make successful login this value wont change till you make logout");
}
& now just change the value in NSUserDefaults while doing logout.
NSLog(#"%#",[[NSUserDefaults standardUserDefaults] valueForkey:#"key"]); // way to access this system dictionary.
For further reference Google for NSUserDefaults Tutorial
Hope this solve some sort of problem of urs. :)
add an integer instance variable, increment it on each viewWillAppear and run your function only if your instance variable is bigger than 1
If you keep a counter it will not work because user can open your view many times without logged in. So what should you do this keep the user's session information. When the user logged in fill in this session info otherwise not. Check this info every time when the user wants to open this tab.

Using iPodMusicPlayer without giving control to iPod in background

I'm developing an app with a very specific focus on shuffling songs within a selected playlist. When the app launches, it lists all the user's playlists, and then when one is selected it loads it into my music player view and get's going. I'm using an MPMusicPlayerController iPodMusicPlayer to handle doing this because I'm pretty new at iOS development and it handles backgrounding and everything nice and easily for me. I want music to continue playing in the background and I like how whatever I change within my app is also reflected in the iPod app. However, I don't want the user to be able to change things in the iPod app and then return to mine. Since my app is all about shuffling, the user could easily go into iPod and disable shuffle, then come back to my app and the experience is ruined. I also don't want them to change the playlist from within iPod.
Can anyone help me think of a way to accomplish this? Play/pause/skip/prev/volume is no problem from within iPod (I want that to be possible), but I don't want changing the song queue to be possible. Is there a way I could add a handler in my app that catches if the user changed something while my app was in the background (and if so, stop music and reset my app to the initial screen)? I'd really appreciate any suggestions. I'm hoping something like this is possible before I venture into using AVPlayerQueue or the like (as a side note, can you play DRM'd files with AVPlayerQueue?).
What I would do is set a bool when backgrounded:
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setBool:YES forKey:#"BACKGROUNDED"];
Then, in your handler for the MPMusicPlayerControllerNowPlayingItemDidChangeNotification that you should be implementing so that you have that control, do the following:
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
if ([prefs boolForKey:#"BACKGROUNDED"]) {
[prefs setBool:NO forKey:#"BACKGROUNDED"];
exit(0);
}
It might be too abrupt, depending on when it checks this code (I don't know when it does in your project) but that should accomplish your goal. exit(0) is the way to terminate your app without throwing an exception. Is that helpful?