Luca Bernardi
Luca Bernardi

Reputation: 4199

Preferred way / Design pattern to handling complex configuration on iOS

Suppose that you need to have a series of complex configuration for a series of different Objects. This configuration can be NSString like service's server address, NSNumber like timeout time and so on. I want to impose the following constraint:

My question is: what's the best way to achieve this? Have you ever faced a problem like this? how did you solve it?

Upvotes: 1

Views: 736

Answers (6)

Julien Lebot
Julien Lebot

Reputation: 3092

Require that for the first time use, an internet connection is present and download via HTTPS your config and keep it in memory (encrypted if you want).

Then take advantage of the keychain in iOS, and store your config as a string there (essentially serialize it).

NSString *serializedConfig = ...;
[keychain setObject:serializedConfig  forKey@"MyConfig"];

On subsequent use, retrieve the config stored in the keychain:

NSString *serializedConfig = [keychain objectForKey:@"MyConfig"];

You can find the keychain wrapper and documentation on the Apple Docs site.

Upvotes: 0

djromero
djromero

Reputation: 19641

Take advantage of Xcode build system. You can have Xcode configuration files for any build configuration (Debug, Release, etc) and target combination.

These files support inheritance to simplify sharing configuration. There is no a single way to define the options. A simple one is to use GCC_PREPROCESSOR_DEFINITIONS or CFLAGS or whatever your compiler will take.

TargetX.xcconfig:

GCC_PREPROCESSOR_DEFINITIONS = STAGE=2 SERVER_URL='www.wuonm.com'

With configured values is fairly trivial to build the required NSString or NSNumber objects. Tip: you will require some kind of stringification.

It's quite similar to using #define but IMHO it's much cleaner and structured if you invest some time understanding how xcconfig files work.

Upvotes: 2

victor.t
victor.t

Reputation: 454

Your static library should provide some interface to set current configuration that will be set in runtime.

SetCurrentConfiguration(Configuration config);

Then "client" can configure it with needed configuration in runtime. Second step is load configuration from specified source, let's say xml file and inject it to static library via method above.

If you don't want users to modify configuration files you can use some sort of encryption and then decrypt on the fly.

Upvotes: 0

Christian
Christian

Reputation: 318

I faced this same issue with server URLs used in different classes and constant numbers like colors, sizes and pretty much any configuration needed to be easily changed. The best solution I found was creating a header file like Constants.h, the content of this header file was:

#define MAX_DIST 1000
#define MIN_DIST 300
#define ANIMATION_DURATION 0.010
#define PIXEL_MOVES 7
#define SENSITIVITY 14
#define VIEW_ANGLE 30 //Range of vision divided by 2
#define RAD_POS_X 415
#define RAD_POS_Y 15
#define BUTTON_VIEW_WIDTH PIXEL_MOVES*360
#define SCREEN_HEIGHT 480
#define BUTTON_WIDTH_CLOSE 180
#define BUTTON_HEIGHT_CLOSE 100
#define BUTTON_WIDTH_MEDIUM 100
#define BUTTON_HEIGHT_MEDIUM 60
#define BUTTON_WIDTH_FAR 60
#define BUTTON_HEIGHT_FAR 40
#define BUTTON_Y_POSITION_CLOSE 200
#define BUTTON_Y_POSITION_MEDIUM 135
#define BUTTON_Y_POSITION_FAR 90
#define SERVICE_URL @"http://my.server.com/SoapServer/SoapServiceWS"//

you can even define common functions like

#define DEGREES_TO_RADIANS(__ANGLE__) ((__ANGLE__) / 180.0 * M_PI)

This way i have been able to configure every aspect of my app from one single file and you can use #ifdef like you said to manage different compilations. Of course, you must import the file Constants.h in any class that will need to access any of these constants.

Upvotes: 0

trumpetlicks
trumpetlicks

Reputation: 7085

There are many questions that arise with this post:

  1. Why do you need this level of protection on your input configuration?
  2. Is the point that you dont wish the user to be able to modify your configuration, or is it that you dont wish them to be able to KNOW it at all?
  3. If you beleive the theory that SW cannot protect SW, then truly what level of pain are you willing to put yourself through in order to put the hacker through enough pain they dont want to hack your SW (because lets face it, thats all you are really going to get, see my comments above about encryption)
  4. I somewhat agree with getting your configuration from the internet, but this only will work IFF you are expecting an internet capability present in order to use your app. If you do this and you also want some level of protection then you are going to have to use some secure protocol (Like SSL) for downloading it.
  5. If you truly wish your app to be able to be used locally (without internet access), then I would say that true security of your configuration is simply immposible, as you dont control the OS, your dont control the HW your SW is running on, etc...
  6. Putting your app on the iPhone probably means that you are hoping for a fairly large amount of downloads. This means the amount of hands touching it and potentially being able to take a CRACK at it are also large. The only way to gain security in this case (as no SW really is), is to make the value of hacking it to get your configuration not worth all that much. If the value is low, then no hacker will care to try and crack it!

Upvotes: 0

NSProgrammer
NSProgrammer

Reputation: 2396

If these values are constant for each build configuration, why not put them in your code as constants? I don't really see why you need to externalize these settings if they are constants that vary by config. Your ifdef selection of the settings would be just as effective (and faster) with these constants declared in a private header.

If these settings somehow change during the running of the app (not from build to build but within the confines of running a single build of the app) then externalizing these settings would be appropriate.

Upvotes: 0

Related Questions