views:

67

answers:

3

I'm trying to reuse a group of Obj-C clases between iPhone applications. The values that differ from app to app have been isolated and I'm trying to figure out the best way to apply these custom values to the classes on an app-to-app basis.

Should I hold them in code?

// I might have 10 customizable values for each class, that's a long signature!
CarController *controller = [[CarController alloc] initWithFontName:@"Vroom" engine:@"Diesel" color:@"Red" number:11];

Should I store them in a big settings.plist?

// Wasteful!  I sometimes only use 2-3 of 50 settings!
AllMyAppSettings *settings = [[AllMyAppSettings alloc] initFromDisk:@"settings.plist"];
CarController *controller = [[CarController alloc] initWithSettings:settings];
[settings release];

Should I have little, optional n_settings.plists for each class?

// Sometimes I customize
CarControllerSettings *carSettings = [[CarControllerSettings alloc] initFromDisk:@"car_settings.plist"];
CarController *controller = [[CarController alloc] initWithSettings:carSettings];
[carSettings release];

// Sometimes I don't, and CarController falls back to internally stored, reasonable defaults.
CarController *controller = [[CarController alloc] initWithSettings:nil];

Or is there an OO solution that I'm not thinking of at all that would be better?

+1  A: 

I would personally consider some kind of "settings" class, in the tradition of Objective-C data sources. Set up a class that's responsible for being a "data source" for each individual app: have it provide either a set of methods for the values you need for that particular app, or a single "getValueForKey"-style method that returns the appropriate value.

Either way, the solution:

  • Keeps values in code
  • Removes the overhead of one massive plist for every setting, some of which may not be used
  • Removes the work of splitting out bunches of tiny plist files
  • Allows you to have other classes call your data source wherever they need it
  • Gives you the flexibility of OO (you could, in theory, subclass your data source should the situation or need arise)
  • Localizes the changes you need to make; just include the data source class as part of the set of classes you're reusing from app to app, and tweak just that class as appropriate (rather than having to change things throughout other classes)
  • Lets you set reasonable defaults - or even throw exceptions - for data values you don't expect to be needed in a particular application, without the need for explicit fallback code in every calling class (write the default or exception once in the data source class)
Tim
I am accepting this answer because of the detailed list of pros here. There was very little voting to guide me - so I really don't know if this was the "best" answer or not ... perhaps I needed to give more context to my question? Thanks to the other answers too - I learned a lot from them.Also, the three answers here seem to all suggest using a protocol (delegate or datasource).
Prairiedogg
+1  A: 

I would give a delegate member to each class to ask what the fine details should be. What font should I use? I'll go ask my delegate. It does not have to be the same delegate for each class or instance, but it can be. For values that can have defaults, use respondsToSelector: to allow for optional delegate methods.

You could make the delegate go look in an xml/plist file for the details, in which case you have it all in one place and can even download a new file to change little details.

All your classes can have the same initWithDelegate: method, which makes it easier to instantiate one without knowing what it is.

drawnonward
This seems to be what the other two answers are saying: define a protocol and create a delegate that implements it.
Prairiedogg
+1  A: 

Prariedogg,

Absolutely externalize the settings into something like a plist. You can even have multiple plists that align to the particular situation (e.g. settingsMac.plist, settingsIPhone.plist).

When your app determines what environment it is running in, it loads the appropriate settings via a delegate or a central singleton.

By externalizing it you will reduce the average maintenance cost of the application. There is less cost to managing and deploying plist updates than recompile/retest/repackage/redeploy.

-- Frank

Frank C.
This makes a lot of sense and was the impetus for my original design. As the schema of the settings class changes, I was getting tired of going back and manually updating all of the settings files in the 4-5 apps that reference this code, so I was looking around for a better solution - perhaps this one is already a good compromise. And everyone seems to agree that defining a protocol is the way to go.
Prairiedogg