How to save state of the app when app terminates? - iphone

I am trying to save the app state by encoding when the app terminates.
I've found the solution related this issue.
But I don't know how to use.
I am really trying to make encoding and decoding like this:
http://cocoaheads.byu.edu/wiki/nscoding
in CustomObject.h
#interface CustomObject : NSObject <NSCoding>
{
NSArray *someArray;
}
in CustomObject.m
#implementation CustomObject
// Other method implementations here
- (void) encodeWithCoder:(NSCoder*)encoder {
[encoder encodeObject:someArray forKey:#"someArray"];
}
- (id) initWithCoder:(NSCoder*)decoder {
if (self = [super init]) {
someArray = [[decoder decodeObjectForKey:#"someArray"] retain];
}
return self;
}
#end
My object to save is another NSArray. Not "someArray" in CustomObject. We call it that "MySaveObject".
I want to pass "MySaveObject" to "someArray" in CustomObject.
Actually I don't know how to encode "MySaveObject" and to pass to "someArray" in CustomObject.
Thanks in advance.

You have to make sure that the objects contained in the array are also able to be encoded. If those objects are custom objects, you'll have to implement NSCoding in them yourself.

Related

Using 'id' when writing methods for stacks of primitive data types?

I am writing a simple calculator app. I want to implement a stack to store the operators the user enters. Originally, I wanted to use chars but ran into some issues when I tried to use the removelastobject and last object for my pop method and addobject for my push method.
Instead I have used id as the type. Is this wrong or are there better ways of solving this issue?
In my .h:
//Brain.h
-(void)pushOperator:(id)op;
In my .m:
//Brain.m
#import Brain.h
#interface CalculatorBrain()
#property (nonatomic,strong) NSMutableArray *operandStack;
#property (nonatomic,strong) NSMutableArray *operatorStack;//This is the one I'm asking about
#end
#implementation CalculatorBrain
#synthesize operatorStack = _operatorStack;
- (NSMutableArray *) operatorStack
{
if (! _operatorStack)
{
_operatorStack = [[NSMutableArray alloc] init];
}
return _operatorStack;
}
-(void)pushOperator:(id)op
{
[self.operatorStack addObject:op];
}
-(id)popOperator
{
NSObject *op = [self.operatorStack lastObject];
if (op)
{
[self.operatorStack removeLastObject];
}
return op;
}
From what I understand, your operator isn't an object type, but rather a basic data type. You can pass an NSValue which can then be claimed as an id, but I'm pretty sure you'd be better suited with a specific primitive value.
If you setup your methods to receive char pointers, then you should be fine.
Using id would be okay, but I think you may want to use an abstract class and derive your operators from that. Then you can use
-(void)pushOperator:(MyOperator)op;
NSArray only stores objects; you can't store primitive types in one. If you just want to store values, you can wrap them in instances of NSNumber or NSValue.

universal array in objective C

I am making my first app, and already made it on android, and am now trying to make it on iphone, but have no objective c experience. The app is super simple except for one part, the array.
The app has a button, that when pressed, needs to store info into an array. The problem I am running into is that when I create the array in the method where the button-click actions take place, every time I click the button it creates a new array, defeating the point of the array. When I make the array outside of the method, it either doesn't pass into the method (error says undefined) or, when I declare the object in the .h file, the program compiles, but when I hit the button it crashes.
Any help would be greatly appreciated. Examples would be great, but even if someone could point me in the right direction of things to look up, that would save me from going bald.
Try something like this (this isn't ARC) -
#interface MyViewController : UIViewController {
NSMutableArray *myArray;
}
#implementation MyViewController
-(id)init {
self = [super init];
if (self) {
myArray = [[NSMutableArray alloc] init];
}
return self;
}
-(void)dealloc {
[myArray release];
[super dealloc];
}
-(IBAction)buttonPressed {
[myArray addObject:someObject];
}
#end
You need to declare your array as an instance variable (AKA "ivar") inside the curly braces section of the the interface declaration in your .h file, and also initialize it in your designated initializer.
In the .h file:
#interface MyClass : NSObject {
NSMutableArray *myArray
}
// methods
#end
In the .m file:
-(id)init {
self = [super init];
if (self) {
myArray = [NSMutableArray array];
}
return self;
}
Now you can use myArray in all instance methods of your class.
EDIT: This sample assumes that you are using automated reference counting. Since this is your first app, using ARC is a good idea (XCode asks you if you would like to use it when you create a new project).

How To Add Data To App To Test Core Data Model

I have some discussion in this question regarding my core data model objects, etc : How To Achieve This Using Core Data
I want to know if and how I can add data to my App Delegate to mock the data that users will input into the app. I can then setup all the tableviews and views that use core data and make sure everything is working and hooking up properly.
Then once everything is all set, I can remove this data and switch it to input data from the user.
Can anyone help with this? Thanks!
You need to create a Data class where you can set the properties of variables or in your case arrays (for displaying data in UITableView). Implement a class method in data class which checks that object has been instantiated or not. If not, it does that. It is something like this :
//DataClass.h
#interface DataClass : NSObject {
NSMutableArray *nameArray;
NSMutableArray *placeArray;
}
#property(nonatomic,retain)NSMutableArray *nameArray;
#property(nonatomic,retain)NSMutableArray *placeArray;
+(DataClass*)getInstance;
#end
//DataClass.m
#implementation DataClass
#synthesize nameArray;
#synthesize placeArray;
static DataClass *instance =nil;
+(DataClass *)getInstance
{
#synchronized(self)
{
if(instance==nil)
{
instance= [DataClass new];
}
}
return instance;
}
Now in your view controller you need to call this method as :
DataClass *obj=[DataClass getInstance];
And use the arrays.
This way you can assign data without disturbing AppDelegate, which is a good practice.

Objective C: store variables accessible in all views

Greetings,
I'm trying to write my first iPhone app. I have the need to be able to access data in all views. The data is stored when the user logs in and needs to be available to all views thereafter.
I'd like to create a static class, however I when I try to access the static class, my application crashes with no output on the console.
Is the only way to write data to file? Or is there another cleaner solution that I haven't thought of?
Many thanks in advance,
Use a singleton class, I use them all the time for global data manager classes that need to be accessible from anywhere inside the application. You can create a simple one like this:
#interface NewsArchiveManager : NetworkDataManager
{
}
+ (NewsArchiveManager *) sharedInstance;
#end
#implementation NewsArchiveManager
- (id) init
{
self = [super init];
if ( self )
{
// custom initialization goes here
}
return self;
}
+ (NewsArchiveManager *) sharedInstance
{
static NewsArchiveManager *g_instance = nil;
if ( g_instance == nil )
{
g_instance = [[self alloc] init];
}
return g_instance;
}
- (void) dealloc
{
[super dealloc];
}
#end
I don't know what you mean with "static class", but what you want is a singleton. See this question for various methods on how to set one up.

Memory Management in Objective-C

I wanna ask if I allocated an instance variable for private use in that class, should i release it immediately on site, or i can depend on dealloc function. (because maybe i will need it on other function) ?
//Player.h
#interface Player : NSObject
{
NSMutableArray * objectArray;
}
- (void)awake;
- (void)add;
#end
//Player.m
#implementation Player : NSObject
{
-(id) init {
self = [super init];
if (self != nil ){
[self awake];
[self add];
}
return self;
}
- (void) awake {
objectArray = [[NSMutableArray alloc] init]; //is it cause leakage?
[objectArray addObject:#"foobar"];
}
- (void) add {
[objectArray addObject:#"foobar2"];
}
- (void) dealloc {
[objectArray release];
[super dealloc];
}
}
#end
or should i using property to set the objectArray iVar?
//Player.h
#interface Player : NSObject
{
NSMutableArray * objectArray;
}
#property (nonatomic,retain)NSMutableArray* objectArray;
- (void)awake;
- (void)add;
#end
//Player.m
#implementation Player : NSObject
{
-(id) init {
self = [super init];
if (self != nil ){
[self awake];
[self add];
}
return self;
}
- (void) awake {
self.objectArray = [[NSMutableArray alloc] init autorelease]; //cause leakage?
[objectArray addObject:#"foobar"];
}
- (void) add {
[objectArray addObject:#"foobar2"];
}
- (void) dealloc {
[objectArray release];
[super dealloc];
}
}
#end
if both of them doesn't cause a leakage, what type should i use?
should i always set iVar property, and access iVar value with self even if i only want to use it in this class?
I like to take the stance that if the instance variable should not be visible outside of the class then it should not be implemented as a property. But it's a personal thing that other developers may not agree with.
Either way you would need to release the objectArray in your classes dealloc method - which is what you're currently doing.
However you need to be careful with your awake method - if it's invoked multiple times then objectArray is leaked. This is the downside of not using properties. A use of self.objectArray = [[NSMutableArray alloc] init] here would have released the previous object.
In my opinion, you should only declare properties in your header if other objects are allowed to use them. There is no good reason why you would provide an -add: method (as in your example) that adds something to your array while also providing a getter for your array so other objects can manipulate it directly. It's called encapsulation.
If you do want to have the benefits of generated getters/setters for your implementation file, you can always use a class continuation (a nameless category) inside your implementation file and include your property declarations there. That way you get real, auto-generated properties that are only visible to your class' implementation.
Personally, I wouldn't use any getter or setter methods in your example. Just allocate the NSArray in your -init and release it in -dealloc. If this -awake method of yours might be called multiple times, just add an [objectArray removeAllObjects] call and you're sure to have an empty array without worrying about memory management.
It is very likely that memory will leak in your first example because you are not sending release to the previously set instance variable (if it already existed).
This is why you should use property setters - they handle all of this stuff for you.
Also, since you are obtaining ownership of the instance variable through the property (which is defined with the retain keyword), you will definitely leak memory if you don't send the instance variable the -release message in your -dealloc method.
So the verdict is that you should use the second example, not the first.