Model class for NSDictionary information with Lazy Loading
My application utilizes approx. 50+ .plists that are used as NSDictionaries.
Several of my view controllers need access to the p开发者_StackOverflow中文版roperties of the dictionaries, so instead of writing duplicate code to retrieve the .plist, convert the values to a dictionary, etc, each time I need the info, I thought a model class to hold the data and supply information would be appropriate.
The application isn't very large, but it does handle a good deal of data. I'm not as skilled in writing model classes that conform to the MVC paradigm, and I'm looking for some strategies for this implementation that also supports lazy loading..
This model class should serve to supply data to any view controller that needs it and perform operations on the data (such as adding entries to dictionaries) when requested by the controller
functions currently planned:
- returning the count on any dictionary
- adding one or more dictionaries together
Currently, I have this method for supporting the count lookup for any dictionary. Would this be an example of lazy loading?
-(NSInteger)countForDictionary: (NSString *)nameOfDictionary {
NSBundle *bundle = [NSBundle mainBundle];
NSString *plistPath = [bundle pathForResource: nameOfDictionary ofType: @"plist"];
//load plist into dictionary
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithContentsOfFile: plistPath];
NSInteger count = [dictionary count]
[dictionary release];
[return count]
}
(Not an answer, but...) have you thought about using Core Data? It seems like it would be much better suited to what you're trying to do than dealing with 50 (!) plists of dictionaries...
You can have the object implement all of its properties in terms of that dictionary—that is, have the object own a dictionary, and have its accessors retrieve values from and store values in that dictionary by sending it objectForKey:
and setObject:forKey:
messages.
Then, have a method that checks whether the dictionary is loaded, and loads it if not:
- (void) loadDictionaryIfNecessary {
if (myDictionary == nil) {
<#Load the dictionary.#>
}
}
Then send yourself a loadDictionaryIfNecessary
message at the start of every accessor. (Obvious pitfall: If you forget to include this statement in an accessor, the accessor will appear to not work.)
The result of this is that you can initialize one of these objects without it loading the dictionary immediately. It'll simply copy the path or something to another instance variable, so that it can use that to load the dictionary when something first tries to access one of the object's properties (which is the first time it'll need the dictionary for anything).
You can't lazy-load individual properties, though. You can only load the whole dictionary at once.
Another way would be to turn the imaginary table of data 90°, and have a dictionary for each property, with its keys being identifiers of objects. (You will need to come up with a suitable persistent-identifier scheme yourself.) This could be a win if you frequently retrieve the same property of a whole bunch of objects at once, without touching other properties. It would be much more complex to implement, though, since accessing the property of one object would force the load for all of its brothers. It would also make setting the properties much more expensive, since you'd be loading, changing, and saving the property file (which, remember, contains all the objects' values for the property) for every property-set.
Definitely profile and prove that you have a performance problem before you undertake that latter solution. Even then, Core Data might be easier.
If you're storing your data in a plist, I'm not sure it's possible to load it lazily, since plists are XML and as far as I know XML parsers don't work lazily.
精彩评论