1

I have an iPhone application that pulls some JSON data from a server and then parses it into an array of dictionaries which contains sub-arrays and sub-dictionaries.

Right now I have this stored in an ivar timeTablethen copying it to filteredTimetable before looping through filteredTimetable and removing the objects I don't need.

The problem I am having is when I try restore the array so it can be filtered again. The objects that have been removed previous from the copied NSArray are removed from the original NSArray too.

filteredTimeTable = [[NSMutableArray alloc] initWithArray:timeTable copyItems:YES];

I assume this is because filteredTimeTable is simply storing a pointers to the objects in timeTable rather than copying the memory.

Here is an example of my data structure:

    [
        {"time":"09:00",
        "events": [
            { "module":"COMP319", "type":"lecture", "room":"BROD-108:80" }
            { "module":"COMP320", "type":"lab", "room":"BROD-LT" }
        ]},

When I remove a module that is no longer required I can't restore the element.

So is there anyway to do a full copy including all the sub-objects?

Ashley
  • 2,256
  • 1
  • 33
  • 62

3 Answers3

2

as today (iOS7, it exists from iOS5 on) the fastest way to deep copy Foundation objects (NSDictionary, NSArray, NSString, NSNumber...) even in complex structure (array inside a dictionary, inside an array and so on...) is to use JSON serialization.

NSData *buffer = [NSJSONSerialization dataWithJSONObject:srcObject options:0 error:nil];
id mutableDeepCopiedObject = [NSJSONSerialization JSONObjectWithData:buffer options:NSJSONReadingMutableContainers+NSJSONReadingMutableLeaves error:nil];

you can also change the options of deserialization to get an immutable copy if needed.

2

You could just keep the original JSON string around and re-parse it.

If you don't want to do that for some reason, and if it's all valid property list objects (NSArray, NSDictionary, NSString, NSNumber, NSDate, NSData), the simplest approach is to use property list serialization:

NSData *archive = [NSPropertyListSerialization dataWithPropertyList:originalObject format:NSPropertyListBinaryFormat_v1_0 options:0 error:NULL];
NSMutableArray *copiedObject = [NSPropertyListSerialization propertyListWithData:archive options:NSPropertyListMutableContainers format:NULL error:NULL];
rob mayoff
  • 375,296
  • 67
  • 796
  • 848
1

I recommend making a model object for whatever your dictionaries represent. Make your class able to create an object from a dictionary, and the objects able to copy themselves correctly. You could do this for the time tables, the events, or both. You can then use initWithArray:copyItems: to copy an array of time tables or events.

As a bonus, using real model objects instead of dictionaries will make your code cleaner.

Right now I have this stored in an ivar timeTablethen copying it to filteredTimetable before looping through filteredTimetable and removing the objects I don't need.

You might even go so far as to make the model objects managed objects, using Core Data. Then you can use fetch requests to do the filtering, and depending on what you're doing, you may be able to use NSFetchedResultsController to let Core Data do even more for you.

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370