After four weeks of learning Objective-C for the iPhone, my first useful application is almost finished. However, I still need to save several instance variables whenever the current view is changed and to reload them when the view is reopened.
I have no trouble loading variables with basic C types like int and BOOL, but am having difficulty with a linked list made of Objective-C objects.
The linked list consists of memory accessed by three pointers: startPointer, currPointer, and endPointer. Each element consists of a last pointer, a next pointer, a pointer to a nested linked list (nestedPtr), and some variables.
My first attempt was to do the following in the loading code:
//dataStorageObj will contain the values to be loaded
dataStorageObj = [[DataSaver alloc] init];
NSData *data =[[NSMutableData alloc] initWithContentsOfFile:[documentsDirectory stringByAppendingPathComponent:@"Archive"]];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
dataStorageObj = [unarchiver decodeObjectForKey:@"KeyForViewA"];
[unarchiver finishDecoding];
//****************************
//Simple variables loaded here
//****************************
//DataSaver is a class with methods to retrieve its instance variables
//The methods are named after the values they retrieve
startPointer = [dataStorageObj startPointer];
currPointer = [dataStorageObj currPointer];
endPointer = [dataStorageObj endPointer];
[unarchiver release];
[data release];
I placed a debug point at the end and all of the variables had the correct values. Actually accessing the values in the code (doing so in the console worked) resulted in *EXC_BAD_ACCESS* messages.
Next, I changed the linked list loading lines to the following:
startPointer = [[PointerClass alloc] initPointerFromList:[dataStorageObj startPointer]];
currPointer = [[PointerClass alloc] initPointerFromList:[dataStorageObj currPointer]];
endPointer = [[PointerClass alloc] initPointerFromList:[dataStorageObj endPointer]];
The initPointerFromList method:
-(PointerClass *)initPointerFromList:(PointerClass *)theList
{
last = theList.last;
nestedPointer = [[NestedPointerClass alloc] initNestedPointerFromList:theList.nestedPointer];
//****************************************
//Other variables loaded from theList here
//****************************************
if (theList.next != nil)
{
next = [[PointerClass alloc] initPointerFromList:theList.next];
}
return self;
}
The problem now was that the pointers were all pointing to individual linked lists, so I wrote methods to retrieve the start and end locations of the linked list referred to by currPointer:
currPointer = [[PointerClass alloc] initPointerFromList:[dataStorageObj currPointer]];
endPointer = [currPointer lastElement];
startPointer = [currPointer firstElement];
My question is threefold:
- Is it necessary to use methods such as initPointerFromList to allocate memory for a loaded linked list?
- Is there a more efficient way to maintain the relationship between currPointer, endPointer, and startPointer than by searching through the list using the lastElement and firstElement methods?
- Is there something wrong with the techniques behind the loading code I have presented? Without it, I have no problems; with it, I still get *BAD_ACCESS* messages. I want to know if these messages are tied to the loading code or if to the way I have handled object allocation throughout the rest of my application.
Thanks in advance!